【问题标题】:Updating Column having index causing deadlock更新具有导致死锁的索引的列
【发布时间】:2020-05-08 11:21:06
【问题描述】:
Update XyzTable set state ='second' where pgmNumber = 'prog123' and state = 'first'

状态列是只有 4 个值的低基数列。 state 和 pgmNumber 列都有单独的索引。

每个 pgmNumber 有一行。

即使上述查询与不同的 pgmNumber 并发运行,也会发生死锁。

解决问题的最佳方法是什么

【问题讨论】:

  • 您要更新的列不在 where 子句中 .. 所以 .. 相关索引不参与更新操作(但只是在行的 fecth 期间).. 可能你有一些在您尝试更新时插入或更新表的其他用户.. .. 无论如何,请确保您已自动提交 ON 或在每次更新后快速提交,以便队列更新不会被未提交的查询阻塞
  • 不,它在哪里

标签: mysql indexing innodb deadlock database-administration


【解决方案1】:

发生死锁是因为“状态”列的索引页被查询锁定。

如果“状态”列只有 4 个不同的值,则索引可能不是很有用,即它没有加快查询速度。请考虑删除“状态”列的索引。

另外,在报告 InnoDB 死锁时,请发布“SHOW ENGINE INNODB STATUS”的输出。

【讨论】:

  • 对于非唯一索引,查询时不会触及索引。相反,索引更新被缓冲在“更改缓冲区”中以供以后处理。
  • 由于“状态”上的索引正在更新而发生死锁,同时运行时相同的查询会创建死锁。除了删除索引之外还有其他选择吗?就像将索引提示放在查询中,比如 force 或使用 index(pgmNumber) ?这行得通吗?
【解决方案2】:

UPDATE 将受益于复合索引:

INDEX(pgmNumber, state)

死锁可能不应该发生。所以,请回答一些问题:

请提供SHOW CREATE TABLE

它与什么查询死锁?

UPDATE 是多语句事务 (BEGIN...COMMIT) 的一部分吗?如果是这样,让我们​​看看其他查询。

你在同一行有SELECT吗?如果有,最后有FOR UPDATE吗?

在低基数列上建立索引很少有用。放下你的INDEX(state)

【讨论】:

  • 并发运行时相同的查询创建死锁。除了删除索引之外还有其他选择吗?就像将索引提示放在查询中,比如 force 或使用 index(pgmNumber) ?这行得通吗?
  • @user2862544 - 删除 INDEX(state) 是清理,而不是解决死锁。添加复合索引可能是一种解决方法。
  • 谢谢瑞克,假设我们不能做任何 ddl 更改,那么我们可以把索引提示像 force index(pgmNumber) 那样工作吗
  • @user2862544 - 我不确定。我希望“提示”不太好。是什么阻止了 DDL 更改?
猜你喜欢
  • 1970-01-01
  • 2020-05-23
  • 2015-06-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 2015-12-16
  • 2018-04-20
相关资源
最近更新 更多