MySQL行锁和表锁

原创
2021/07/06 11:06
阅读数 42

说明

InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁。否则是表级别。

#for update的注意点
for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。

要测试for update的锁表情况,可以利用MySQL的Command Mode,开启二个视窗来做测试。

行锁和表锁测试

1、只根据主键进行查询,并且查询到数据,主键字段产生行锁。

begin;
select * from goods where id = 1 for update;
commit;

2、只根据主键进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 for update;
commit;

3、根据主键、非主键含索引(name)进行查询,并且查询到数据,主键字段产生行锁,name字段产生行锁。

begin;
select * from goods where id = 1 and name='prod11' for update;
commit;

4、根据主键、非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 and name='prod12' for update;
commit;

5、根据主键、非主键不含索引(name)进行查询,并且查询到数据,如果其他线程按主键字段进行再次查询,则主键字段产生行锁,如果其他线程按非主键不含索引字段进行查询,则非主键不含索引字段产生表锁,如果其他线程按非主键含索引字段进行查询,则非主键含索引字段产生行锁,如果索引值是枚举类型,mysql也会进行表锁,这段话有点拗口,大家仔细理解一下。

begin;
select * from goods where id = 1 and name='prod11' for update;
commit;

 

6、根据主键、非主键不含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 and name='prod12' for update;
commit;

7、根据非主键含索引(name)进行查询,并且查询到数据,name字段产生行锁。

begin;
select * from goods where name='prod11' for update;
commit;

8、根据非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where name='prod11' for update;
commit;

9、根据非主键不含索引(stock)进行查询,并且查询到数据,stock字段产生表锁。
 

begin;
select * from goods where stock='1000' for update;
commit;

10、根据非主键不含索引(stock)进行查询,没有查询到数据,stock字段产生表锁。

begin;
select * from goods where stock='2000' for update;
commit;

11、只根据主键进行查询,查询条件为不等于,并且查询到数据,主键字段产生表锁。

begin;
select * from goods where id <> 1 for update;
commit;

12、只根据主键进行查询,查询条件为不等于,没有查询到数据,主键字段产生表锁。

begin;
select * from goods where id <> 1 for update;
commit;

13、只根据主键进行查询,查询条件为 like,并且查询到数据,主键字段产生表锁。

begin;
select * from goods where id like '1' for update;
commit;

14、只根据主键进行查询,查询条件为 like,没有查询到数据,主键字段产生表锁。

begin;
select * from goods where id like '1' for update;
commit;

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部