mysql - 如何解决MySQL由于hibernate envers审计而导致的死锁?

标签 mysql hibernate hibernate-envers database-deadlocks

虽然并行运行几个事务,但大多数时候我都会遇到死锁:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2019-09-04 06:19:12 0x2b01917c7700
*** (1) TRANSACTION:
TRANSACTION 14470484, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 13 lock struct(s), heap size 1136, 7 row lock(s), undo log entries 4
MySQL thread id 69372, OS thread handle 47285779531520, query id 10366178979 172.31.19.11 master updating
update `VerificationActionLog_AUD` set `REVEND`=427956 where `id`=138136 and `REV`<> 427956 and `REVEND` is null
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 7307 page no 1108 n bits 128 index PRIMARY of table `TestDB`.`VerificationActionLog_AUD` trx id 14470484 lock_mode X waiting
Record lock, heap no 60 PHYSICAL RECORD: n_fields 27; compact format; info bits 0
...

*** (2) TRANSACTION:
TRANSACTION 14470485, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
11 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 4
MySQL thread id 69395, OS thread handle 47285735814912, query id 10366178981 172.31.19.11 master updating
update `VerificationActionLog_AUD` set `REVEND`=427957 where `id`=138137 and `REV`<> 427957 and `REVEND` is null
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 7307 page no 1108 n bits 128 index PRIMARY of table `TestDB`.`VerificationActionLog_AUD` trx id 14470485 lock_mode X locks rec but not gap
Record lock, heap no 60 PHYSICAL RECORD: n_fields 27; compact format; info bits 0
...

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 7307 page no 1108 n bits 128 index PRIMARY of table `TestDB`.`VerificationActionLog_AUD` trx id 14470485 lock_mode X waiting
Record lock, heap no 60 PHYSICAL RECORD: n_fields 27; compact format; info bits 0
...

*** WE ROLL BACK TRANSACTION (2)

我试图推断这些陈述所解释的内容。据我了解,事务2持有TestDB.VerificationActionLog_AUD主索引的锁。与此同时,事务 2 也在等待相同的锁。单个事务怎么可能持有并等待同一个锁?

我从这些陈述中推断出错误了吗?我该如何继续解决这些僵局。另外,死锁仅适用于由 envers 在幕后维护的 AUD 表,如何解决这个问题?

最佳答案

这是由于间隙锁而发生的。间隙锁是对索引记录之间间隙的锁定,或者对第一个索引记录之前或最后一个索引记录之后的间隙的锁定

假设您有相邻的 id ,1 和 2。当从 2 个不同的 session 同时执行过程时,每个 session 都会在两个索引记录上放置间隙锁(使用 id 值 1 和 2 - 也可能是 0、4、5,但为了简单起见,我们假设为 2),并且它们中的每一个都必须等待另一个释放锁才能执行插入。

Gap locks in InnoDB are “purely inhibitive”, which means they only stop other transactions from inserting to the gap. They do not prevent different transactions from taking gap locks on the same gap. Thus, a gap X-lock has the same effect as a gap S-lock *."

解决方案:

Gap locking can be disabled explicitly. This occurs if you change the transaction isolation level to READ COMMITTED or enable the innodb_locks_unsafe_for_binlog system variable (which is now deprecated). Under these circumstances, gap locking is disabled for searches and index scans and is used only for foreign-key constraint checking and duplicate-key checking.

引用文献:

关于mysql - 如何解决MySQL由于hibernate envers审计而导致的死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57782636/

相关文章:

php - JOIN 或 2 个查询 - 1 个大表,1 个小表,硬件有限

php - laravel 4 preg_replace() : Parameter mismatch

spring - 无法写入 JSON : could not initialize proxy - no Session error

java - 如何仅执行 "Distinct Root"但不为 JPA 生成不同的结果 SQL?

java - 将参数传递给 JSF 函数

java - 防止 Hibernate 关系表被审计

mysql - sql LIKE 不返回预期的行

php - CodeIgniter 状态更改

java - JPA:将上次更新时间存储在单独的表中

java - Hibernate Envers - 在 ValidityAuditStrategy 中支持 JDBC 批处理(allow_identifier_reuse=true)