For example, for a branch transaction, the user performs a delete operation, then the prepare phase is committed, but the global transaction fails, causing the rollback.
// 比如某个分支事务,用户执行了 delete 操作,那么 prepare 阶段,提交了,但是全局事务失败,导致回滚
The current practice is to get all the SQL statements executed by the user through the proxy connection, save before, and atfer image in the undo_log table.
// 目前的做法是通过 代理 connection,拿到用户执行的所有sql语句,保存 before,atfer image 在 undo_log 表中。
If you submit, pass gxid, bxid delete data undo_log
// 如果提交就通过 gxid, bxid 删除数据undo_log
If it fails, the data is rolled back to get the before image.
// 如果失败了,就数据回退搞 before image .
However, delete succeeded, but the global transaction failed, but other transactions, before the rollback, insert the same key data, resulting in the failure to roll back? Either the xa transaction is used, and the data of these changes cannot be modified before the commit/rollback.
// 但是 delete 成功了,但是全局事务失败,但是其他事务,在回滚前,insert了相同key的数据,导致无法回滚? 要么就是采用 xa 事务,这些变更的数据,commit/rollback 前没法修改。
* WE STRONGLY SUGGEST YOU TO DESCRIBE YOUR ISSUE IN ENGLISH *
AbstractUndoExecutor 有三个子类,分别对应 mysql的 insert , delete, update 的反向操作,多个事务,修改同一条数据,怎么确保数据的正确性。
+1
我理解你的意思是:delete 操作回滚时,因为相同主键的记录的插入而违反主键唯一性约束,不能回滚成功。对吧?
实际上,这里是有全局写锁的机制来保障的,delete 操作所在的全局事务二阶段回滚完成前,这条记录的锁是不会释放的,所以相同的主键的记录是不会在这个时机插入进来的。
你可以看一下分支注册 lockKey 相关的逻辑。
那么这样是不是意味着在全局事务commit或者rollback之前,这个锁都要一直锁住?
commit或者rollback 之前,那么所涉及的数据,其他事务是没有办法操作的。
说错了,在本地事务A提交后,数据对于本地事务的其他事务已经可见,那么全局事务还没有提交,由于其他本地事务失败,现在需要回滚,那么A操作的数据是不是要一直锁住,等待全局事务提交或者回滚才释放?
关键在于二阶段的决议,如果决议是回滚,那么一定要全局锁到回滚完成才释放。而如果是决议是提交,那么,锁就可以马上释放。而且锁在 server 端维护,不需要依赖 RM,也就是收到二阶段提交的决议后,马上释放锁。
好的,谢谢,那么是不是意味着分支A事务的锁,要等到BCD分支事务都执行完,此时全局事务开始提交,才能释放,也就是这把锁还是要等到所有的分支事务都提交了才可以释放?
我看了下lockkey的机制是服务端维护的一个锁并非数据库层面的,所以这个锁仅针对fescar发起的事务有效。如上例子A事务包含BCD分支,需要修改TableA,后续事务如果想修改TableA就需要经过lockkey检查,直到A事务释放锁。如果有一个业务操作没有发起事务也去修改TableA,这个是不需要lockkey检查的。如有错误请纠正
同问,比如示例中:
` @Override
@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")
public void purchase(String userId, String commodityCode, int orderCount) throws Exception {
storageService.deduct(commodityCode, orderCount);
orderService.create(userId, commodityCode, orderCount);
} `
orderService.create(userId, commodityCode, orderCount);,此处加入断点。
storageService.deduct成功执行扣减库存后,手动修改数据库中库存。
然后orderService.create执行中产生了回滚。
会导致手动修改或者中间过程修改的数据会丢失。
对于这一点,大家怎么看?
fescar是独立于数据库的,从现在代码看,它是感知不到有其他不通过fescar事务的数据库修改的。不过这种情况可以用之后的MT模式来支持,业务自己定义提交跟回滚的逻辑
看源码对于未开启fescar事务的增删改操作,其实是透传执行的,该情况会加大回滚失败的几率;
通过fescar包装的Statement进行的数据变更操作为何没有fescar事务锁查询操作,锁查询是不是可以很大程度上减少回滚失败的概率。
非fescar事务修改的数据貌似都会被覆盖掉,这个问题怎么解决呢
@xuxiaofei4519 修改需要你加 where 条件,不然都会回滚到undo日志的快照数据
please use the latest version . If you have other questions, please reopen it.
Most helpful comment
我看了下lockkey的机制是服务端维护的一个锁并非数据库层面的,所以这个锁仅针对fescar发起的事务有效。如上例子A事务包含BCD分支,需要修改TableA,后续事务如果想修改TableA就需要经过lockkey检查,直到A事务释放锁。如果有一个业务操作没有发起事务也去修改TableA,这个是不需要lockkey检查的。如有错误请纠正