使用SELECT ... FOR UPDATE
语句时,我遇到了LOCK WAIT TIMEOUT问题。
我准备了我不理解的场景。你能告诉我为什么前三个块立即被执行,但是最后一个块等了吗?
感谢。
-- I'm using MariaDb
-- T1 is the mysql terminal window 1
-- T2 is the mysql terminal window 2
CREATE TABLE `test` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL
) COMMENT='' ENGINE='InnoDB' COLLATE 'utf8_bin';
INSERT INTO test SET name='foo';
T2: START TRANSACTION;
T1: START TRANSACTION;
T1: SELECT * FROM test WHERE id IN (1) FOR UPDATE;
T2: INSERT INTO test SET name='foo'; -- executed immediately
T2: START TRANSACTION;
T1: START TRANSACTION;
T1: SELECT * FROM test WHERE id IN (1,2) FOR UPDATE;
T2: INSERT INTO test SET name='foo'; -- executed immediately
T2: START TRANSACTION;
T1: START TRANSACTION;
T1: SELECT * FROM test WHERE id IN (1,2,3) FOR UPDATE;
T2: INSERT INTO test SET name='foo'; -- executed immediately
T2: START TRANSACTION;
T1: START TRANSACTION;
T1: SELECT * FROM test WHERE id IN (1,2,3,4) FOR UPDATE;
T2: INSERT INTO test SET name='foo'; -- waits for T1 to commit
T2: commit;
T1: commit;
答案 0 :(得分:1)
InnoDB行级锁是index-locks in reality。记录较少的特性 * 是:如果锁定SELECT
没有(或不能)使用(用户定义的)索引,那么只能使用默认的聚簇索引,并且整个桌子被锁定了。
优化器很可能决定索引对于检查" long" IN()
参数列表(可能因为需要扫描大部分表)。这会导致您检测到意外的副作用。
可以通过查看execution plan来确认此假设。
答案 1 :(得分:0)
我认为您假设“select for update”仅锁定UPDATE的行。但是,锁定也适用于INSERT,因为插入可以插入属于原始“select”的记录。该文档声明它“锁定行和任何相关的索引条目”。
http://dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html