目录
以前一直以为排他锁是根据唯一主键进行排他操作,今日测试完毕特此记录
用例代码
CREATE TABLE `test` (
`id` int(11) DEFAULT NULL,
`name` int(11) DEFAULT NULL,
KEY `test` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
insert into test values(1,1)
insert into test values(1,1)
insert into test values(2,2)
insert into test values(3,3)
alter table test add UNIQUE test(`name`)
alter table test add index test(`name`)
alter table test drop index test
start TRANSACTION;
explain select * from test where name = 1 for update
select * from test where name = 1 for update
COMMIT;
start TRANSACTION;
select * from test where name = 1 for update
commit;
实际上排他操作就是根据where后面的查询条件进行相关操作的,并不是只能在进行根据主键id进行相关查询的时候才能进行添加排他操作
根据上述sql用例进行相关测试结果分为以下几种
1. 不添加索引进行排它锁添加
在不添加索引的时候无论此where条件的值在库中是否唯一都会造成全表锁
在开启事务后session1
select * from test where name = 1 for update
在开启事务后session2进行
select * from test where name = 2 for update
时提示锁等待
在加锁是可以通过explain分析将会影响的行可以看出 row = 表内数据总行数 通过上面四条数据得出row = 4
explain select * from test where name = 1 for update
即锁全表了。
2. 通过普通索引字段进行排它锁添加
在此情况加会造成where条件下此索引所有行皆添加了行锁
在开启事务后session1
select * from test where name = 1 for update
在开启事务后session2进行
select * from test where name = 1 for update
时提示锁等待
通过explain分析可以看出row等于此where条件下通过此值索引查出的行个数 通过上面四条数据测试row = 2
3. 通过唯一索引进行排它锁添加
在此情况加和主键进行添加都是一样的,因为索引值是唯一的,只有where条件后的唯一值所在行添加了行锁
通过explain分析可以得出row = 1
4. 根据主键进行排它锁添加
在此条件下和唯一索引一样,都能正常添加排它锁
由此可见,在进行排他锁添加的时候底层是通过索引进行添加的,如果where条件没有索引则会造成锁全表的结果