SELECT 多行 FOR UPDATE 时,会死锁吗?
回答问题 在 MySQL+InnoDB 中,假设我有一个表和两个线程,它们都执行“SELECT ... FOR UPDATE”。假设两个 SELECT 语句最终都选择了多行,例如他们最终都选择了 R42 和 R99 行。这有可能会陷入僵局吗? 我正在考虑这种情况:第一个线程尝试锁定 R42 然后 R99,第二个线程尝试锁定 R99 然后 R42。如果我不走运,两个线程会死锁。 我在 MySQLGl
回答问题
在 MySQL+InnoDB 中,假设我有一个表和两个线程,它们都执行“SELECT ... FOR UPDATE”。假设两个 SELECT 语句最终都选择了多行,例如他们最终都选择了 R42 和 R99 行。这有可能会陷入僵局吗?
我正在考虑这种情况:第一个线程尝试锁定 R42 然后 R99,第二个线程尝试锁定 R99 然后 R42。如果我不走运,两个线程会死锁。
我在 MySQLGlossary 中读到“死锁”
当事务锁定多个表中的行(通过 UPDATE 或 SELECT ... FOR UPDATE 等语句)但顺序相反时,可能会发生死锁。 ...
为了减少死锁的可能性,... 在 SELECT ... FOR UPDATE 和 UPDATE ... WHERE 语句中使用的列上创建索引。
这个 hints 在我的情况下(单表)我不会死锁,可能是因为 MySQL 会自动尝试按主键的顺序锁定行,但我想确定,我在确切地告诉我发生了什么的文档。
Answers
来自 MySQL 文档
InnoDB uses automatic row-level locking. You can get deadlocks even in the case of
transactions that just insert or delete a single row. That is because these operations
are not really “atomic”; they automatically set locks on the (possibly several) index
records of the row inserted or deleted.
http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html
所以一般来说,死锁不是致命的,你只需要再试一次,或者添加适当的索引,这样扫描的行数就会减少,从而锁定的行数就会减少。
更多推荐
所有评论(0)