关于log_status=1的记录

网上都说是防悬挂,具体是指啥又没说清楚。这里先说结论:这个条记录,你可以不用管它。

防悬挂,因为网络延迟或者第一阶段请求丢包,导致第二阶段的回滚请求,先到RM,RM此时没有处理第一阶段请求,没有记录undo_log,所以插入该记录,作为一个防御性的操作,阻止后到的第一阶段请求继续执行。

产生的另一个原因是,请检查项目中是否为多数据源。如果是,需要把seata自动代理关了,一般多数据源都是有开发者已经手动代理了。二阶段的时候,下发找datasource,找到的不是你业务操作数据库的datasource,导致没发现undolog,就插了一条status=1。

1
2
3
# 关闭自动代理
seata:
enable-auto-data-source-proxy: false

关于log_status=0的记录

seata-server宕机后,分支事务的undo_log中将出现log_status=0的记录,重新seata-server后,会自动处理掉这些日志。

异常:ShouldNeverHappenException

1
Error preparing statement. Cause: io.seata.common.exception.ShouldNeverHappenException: [xid:172.19.0.204:8091:9483xxxxxxxxx]get tablemeta failed

解决方案:检查表是否存在。

异常:SQLJoinTableSource

1
java.lang.ClassCastException: com.alibaba.druid.sql.ast.statement.SQLJoinTableSource cannot be cast to com.alibaba.druid.sql.ast.statement.SQLExprTableSource;

出现原因:update语句不能join其他表。

异常:TmTransactionException

1
2
3
4
Failed to begin transaction. 
io.seata.core.exception.TmTransactionException: TransactionException[Fail to store global session]
....
java.lang.reflect.UndeclaredThrowableException: null

查看seata-server是否抛出类似的错误:

1
writeSession error, global session size exceeded, size : 566 maxBranchSessionSize : 512

解决方案:开启全局事务的方法入参太多。

异常:TransactionException

1
TransactionException[Could not register branch into global session xid = 172.32.1.161:8091:113670****4512 status = AsyncComm ]

产生原因:在 @GlobalTransactional 的外面使用 @Transactional 修饰了,例如:

1
2
3
4
5
6
7
8
@Transactional
public void aaa() {
bbb();
}
@GlobalTransactional
public void bbb() {

}