mysql innodb多个索引在查询期间锁定了太多行

时间:2014-11-05 18:10:10

标签: mysql locking multi-index

以下是三个字段中的一些mysql inno_bd表t主键id和多个 btree 索引。 字段A,B,C分别为intintDatetable 问题在于: 我有一个归档t_archive表,用于将记录从t移动到t_archive(如果已经过时)。要移动记录,我使用两个查询:

  • INSERT INTO t_archive SELECT * FROM t WHERE A = 1 AND B = 2 AND C = 3
  • DELETE FROM t WHERE A = 1 AND B = 2 AND C = 3

(正如您所注意到的,满足条件ID为4和5) 在上述查询期间,我尝试UPDATE使用ID进行重新计算:1和8。 从逻辑上讲,没有理由lock记录1,2,3,6,7,8个任何类型的查询,  但它发生了! 由于真正的红色扇区比例子大得多,转移操作需要花费很多时间(大约50秒),我无法使用其他recs(只是UPDATE,其中id = 8) - 获得异常:Lock wait timeout exceeded; try restarting transaction < / p>

有人可以解释为什么会发生这种情况以及如何避免它吗?

2 个答案:

答案 0 :(得分:0)

如果使用更棘手的DELETE查询,问题就会消失:

DELETE t FROM my_table t, 
(SELECT t1.id AS del_id  FROM my_table t1 
WHERE t1.A=1 
AND t1.B=2 
AND t1.C=3) AS del
WHERE t.id=del.del_id;

答案 1 :(得分:0)

如果这是一个“大”表,如果你没有合适的索引,例如INDEX(a,b,c)(按任意顺序),则DELETE需要很长时间才能扫描表格,挂起锁定它获取它们。这存在锁定等待超时或甚至死锁的风险。

如果表格“小”和/或您有一个好的索引,是否会发生超时?

回到为什么DELETE带有子查询以使ids可能侵入性较小的问题:

首先使用最小锁运行SELECT子查询。然后运行DELETE,至少需要对所讨论的2行进行排他锁定。如果它没有超时,我怀疑这是因为在这个“两步”版本中获取锁的时间。