"Seata中在大批量频繁操作相同对象时,记录的Select SQL出现 For Update。
环境:Mysql 隔离级别(READ-COMMITTED)阿里云, Spring Boot , Seata 1.7.0
描述:两个微服务程序批处理读、写表时。 程序未对 SQL 进行 For Update;
但是阿里云以及(SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;)都出现Select语句 锁等待。 这个问题有遇到过吗?我用的是 @GlobalTransactional,没有用GlobalLocks。我本地跟了一下代码 只有 识别到 程序加的For UPDATE才会走 SelectForUpdateExecutor 。"
AT依赖于for update,我理解这个场景的核心是热点数据竞争问题,根本不在for update。update的时候,seata会替你发一条select for update,建议去看官网原理。 for update阻塞只是表象,不是去解决for update的问题,而是共享数据高并发更新的问题。如果你要解决掉for update,就没有全局事物。此群整理至钉群“Seata(分布式事务)”。
这个问题可能是由于Seata在处理大批量频繁操作相同对象时,自动添加了For Update锁导致的。在MySQL的READ-COMMITTED隔离级别下,当一个事务对某个数据行加锁后,其他事务仍然可以对该数据行进行读操作,但是不能进行写操作,直到该事务提交或者回滚。
为了解决这个问题,你可以尝试以下方法:
调整事务的隔离级别。将隔离级别从READ-COMMITTED降低到READ-UNCOMMITTED,这样可以避免Seata自动添加For Update锁。但请注意,这样做可能会导致脏读、不可重复读和幻读的问题。
使用Seata的GlobalLocks功能。通过在@GlobalTransactional注解中添加GlobalLocks参数,可以手动指定需要锁定的数据行。例如:
@GlobalTransactional(name = "myTransaction", rollbackFor = Exception.class, globalLocks = {
@GlobalLock(value = {"tableName"}, lockType = GlobalLockType.SELECT),
@GlobalLock(value = {"tableName"}, lockType = GlobalLockType.UPDATE)
})
public void myMethod() {
// your code here
}
Seata 1.7.0 中出现的这个问题可能是由于 Spring Boot 和 Seata 集成时的某些默认行为导致的。在 Seata 中,当你使用 @GlobalTransactional
注解来声明一个全局事务时,Seata 会自动将读操作(SELECT)转换为带有 FOR UPDATE 子句的查询,以确保在分布式事务中的一致性。
根据你的描述,尽管程序本身没有显式地对 SQL 进行 FOR UPDATE,但在运行过程中却观察到了这个现象。这可能是因为 Seata 在背后进行了这样的处理。如果两个微服务都在频繁地进行批处理读写,并且它们的操作涉及到相同的对象,那么在 READ-COMMITTED 隔离级别下,确实可能会发生锁等待的情况。
对于这种情况,你可以考虑以下几种解决方案:
检查数据访问模式:
确保应用程序不是在并发地修改相同的数据记录。避免在同一时间内对同一记录执行多个更新操作。可以尝试优化业务逻辑,或者使用数据库层面的悲观锁或乐观锁来控制并发。
调整隔离级别:
考虑将数据库的隔离级别从 READ-COMMITTED 更改为 REPEATABLE READ 或 SERIALIZABLE。更高的隔离级别可以减少并发问题,但可能会增加锁定开销和降低性能。
减少事务范围:
尽量减小事务的范围,只包含那些真正需要在事务中执行的操作。这样可以减少锁冲突的机会。
优化Seata配置:
可能需要深入研究 Seata 的配置选项,看看是否有办法关闭 Seata 对 SELECT 语句的 FOR UPDATE 自动转换。这通常可以通过 Seata 的配置文件来进行设置。
使用 GlobalLocks:
虽然你提到当前未使用 GlobalLocks,但是在一些情况下,使用 Seata 提供的 GlobalLocks 功能可以帮助更好地管理分布式锁和事务一致性。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。