主从重复数据源配置导致锁超时问题

149 阅读2分钟

记录开发环境中Spring声明式事务+Sharding-JDBC读写分离的一次踩坑

问题现象:

在一个Spring声明式事务方法中有两个SQL操作,先插入一条新数据,再删除特定数据。这个方法有时候会出现删除操作等待锁超时问题。

问题定位:

  1. 在MySQL客户端测试这个事务,问题不能重现。

  2. 查看锁超时时候,MySQL的事务,锁的情况。发现有两个事务,删除操作会等待锁超时。 查看MYSQL的事务,锁,锁等待。

select * from information_schema.INNODB_TRX;
select * from information_schema.INNODB_LOCKS;
select * from information_schema.INNODB_LOCK_WAITS;
  1. 代码中声明了一个事务,为什么数据库中会有两个事务呢?怀疑跟Sharding-JDBC配置有关系,在开发环境中主从库是同一个数据库。

  2. 开启Sharding-JDBC的日志,日志会记录SQL是由哪个数据源执行的。

    Spring.shardingsphere.props.sql.show = true

  3. 开启日志后发现问题,发现插入SQL的执行数据源是master, 删除SQL数据源是slave. 这就是为什么有两个事务的原因,因为是两个数据库连接。

问题解决:

定位问题后,发现是sharding-jdbc的masterslave配置有问题,配置了masterslave之后,路由规则才正确的成了mastersalve, 这样这个事务就会是同一个数据源连接,保证了真正的事务提交。

spring:
  shardingsphere:
    masterslave:
      load-balance-algorithm-type: xxx
      name: xx
      master-data-source-name: xxx
      slave-data-source-names: xxx

总结:

参考sharding-jdbc的处理事物的方式。一个ShardingConnection会执行多条SQL,可能会涉及不同的数据源,如果SQL执行不会出现逻辑异常的话,会最后统一进行提交。

如果不同的数据源连接的是同一个数据库,并且SQL之间有锁等待的话,可能会出现锁等待超时,因为在最后阶段才会进行事务提交。