启用了 InnoDB 插件的 MySQL 服务器版本 5.1.41。我有以下三个发票表:invoices、invoice_components 和 invoice_expenses。表 invoices 具有 invoice_id 主键。invoice_components 和 invoice_expenses 都与表 invoices 相关联,其中 invoice_id 作为非唯一的 foreign_key(每张发票可以有多个组件和多个费用)。两个表都有这个外键的 BTREE 索引。
我有以下交易:
交易1
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 18 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 18 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 18 FOR UPDATE;
第一个事务一切正常,行被选中并锁定。
交易2
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 19 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 19 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 19 FOR UPDATE;
第二个事务返回ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
第三个查询。
当我尝试 SELECT ... FOR UPDATE 其他发票及其组件和费用时,也会发生同样的情况。似乎第一笔交易已锁定 invoice_expenses 表中的所有行。任何想法为什么会发生这种情况?
附加信息
事务 2 在事务 1 的第三次查询之后开始。服务器上没有其他用户、连接或事务。
该问题发生在默认的 REPEATABLE READ 事务隔离级别中。它通过更改为 READ COMMITTED 级别来修复。这是一个解决方案,但它仍然无法解释为什么问题出现在 invoice_expenses 而不是 invoice_components。