【问题标题】:How to resolve deadlock in MySQL due to hibernate envers auditing?由于休眠环境审计,如何解决 MySQL 中的死锁?
【发布时间】:2020-01-07 00:10:51
【问题描述】:

在并行运行少量事务时,大多数时候我会陷入死锁:

------------------------
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 表,如何解决此问题?

【问题讨论】:

  • UPDATE 语句中可以清楚地看出,您正在使用ValidityAuditStrategy 并在生成新的审计行时更新旧记录的REVEND 列。除非您尝试在同一实体上执行某些嵌套事务行为,否则您不应该遇到死锁。没有看到你的 java 代码和事务处理,很难说。
  • @Naros 感谢您的评论。虽然仍然无法解决它,但现在我有了更好的理解。我有几个问题。 MySQL有嵌套事务吗?我们手动开始并提交事务。我不认为我们在已经运行的事务中开始事务的任何部分。但是我们在事务之间进行刷新。手动刷新会导致嵌套事务吗?
  • 请提供SHOW CREATE TABLE VerificationActionLog_AUD 以及有关同一事务中其他内容的一些线索。另外,这些是在桌子的“末端”吗?
  • 解释一下你所说的“冲洗”是什么意思。
  • 我们正在使用休眠。 stackoverflow.com/questions/3220336/… 给出了很好的解释。也检查答案 2

标签: mysql hibernate hibernate-envers database-deadlocks


【解决方案1】:

这是由于间隙锁而发生的。间隙锁是在索引记录之间的间隙上加锁,或者是在第一条索引记录之前或最后一条索引记录之后的间隙上加锁

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

InnoDB 中的间隙锁是“纯粹的抑制性”,这意味着它们只 阻止其他事务插入到间隙中。他们不阻止 不同的事务在相同的间隙上使用间隙锁。因此,一个 间隙 X-lock 与间隙 S-lock * 具有相同的效果。”

解决方案:

可以显式禁用间隙锁定。如果您更改 事务隔离级别为 READ COMMITTED 或启用 innodb_locks_unsafe_for_binlog 系统变量(现在是 已弃用)。在这些情况下,间隙锁定被禁用 搜索和索引扫描,仅用于外键约束 检查和重复键检查。

参考:

【讨论】:

  • 并在休眠使用属性“hibernate.connection.isolation”中更改隔离级别
  • 很高兴您发现了问题所在。
猜你喜欢
  • 2012-08-03
  • 2020-04-14
  • 2017-08-17
  • 2017-11-25
  • 2014-03-22
  • 2017-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多