mysql - Spring JDBC 应用程序中的 SELECT FOR UPDATE 问题
问题描述
我正在使用SELECT ... FOR UPDATE
语句在我的 SpringBoot 应用程序中实现行级锁定。数据库:MySQL 5.7.28,连接器 - MariaDb java 客户端 2.5.2,连接池 HikariCP 2.7.9,spring boot 版本 - 2.0.3 Release。
持久性是由 Spring JDBC Template 完成的,而不是由 JPA 完成的。我正在使用 Spring Transaction 管理,通过@Transactional
在我的 DAO 方法上添加注释来进行注释。事务代理是通过 AspectJ 编译时编织 ( @EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
) 生成的。我确信事务管理器配置正确。
我已经编写了几个集成测试,这些测试将验证当多个线程竞争更新同一行时出现竞争条件的可能性,该行应该被锁定SELECT ... FOR UPDATE
。
现在,测试在 95% 的情况下都有效,但是,当执行特定的 IT 序列时,有一个测试会失败。
我确信当测试失败时,不会强加行锁。
我已在服务器上启用 MySql 查询日志以帮助进行故障排除。
这是我在第一个线程执行SELECT ... FOR UPDATE
语句时看到的:
2020-01-26T12:54:06.681319Z 1219 Query set autocommit=0
2020-01-26T12:54:36.616097Z 1209 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19qix6lvsfx') FOR UPDATE
似乎自动提交设置在错误的连接对象上。我读对了吗?这些数字1219
和是1209
什么?
当一切正常时,日志如下所示:
2020-01-26T13:24:22.940787Z 1243 Query set autocommit=0
2020-01-26T13:24:36.515016Z 1243 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19xbs7vv53r') FOR UPDATE
任何帮助将不胜感激。
解决方案
我不喜欢autocommit=0
,因为我COMMIT
最终可能会忘记。
SELECT ... FOR UPDATE
仅在您处于事务中时适用(autocommit=0 表示您始终处于事务中)。
您的一般日志片段暗示所有连接都在设置该值,也许是重复的。不,每个连接不受其他连接设置的影响。
您在日志中看到任何 COMMIT 吗?你曾经发出 ROLLBACK 吗?
推荐阅读
- arrays - 如何在 MATLab 中创建增量为 0.01 的样本直方图?
- prometheus - 使用 grafana 持续时间变量重新采样普罗米修斯数据
- javascript - How can I change the collisionFilter of an object so it can no longer interact with MouseConstraint (MatterJS)
- php - Stripe API PHP,获取所有付款方式(我每次都需要客户 ID 吗?)
- python - 更改熊猫数据框格式
- dataframe - 从数据块中的大型 pyspark 数据帧或 koalas 数据帧返回一行的最快方法是什么?
- r - 在 R 中,按顺序对列表的每个元素进行排序,并使用该顺序对列表中的数据进行采样
- delphi - Delphi FMX FormStyle StayOnTop only while app is active
- python - How to print first 5 lines of a sorted csv file?
- amazon-web-services - 如何在 AWS VPC 中找出面向 Internet 的资源(EC2、RDS 等)?