简介
锁从力度上可以分为表锁、页锁、行锁。表锁是将整张表锁了,行锁是将那一行锁了。从对数据的操作角度来分,可以分为读锁和写锁。但是个人觉得,读锁和写锁是针对表锁而言的,行锁好像没有这个区别。
行锁:
可以参考我下一篇博客:https://blog.csdn.net/tuesdayma/article/details/81910117
表锁
概述: 表锁主要正针对于myisam(mysql5.5之前默认存储引擎)的存储引擎而言的,每次对数据库操作都会进行表锁。
特点:
1、开销小,加锁快,无死锁;发生锁冲突的概率高,并发度很低。
2、读锁会阻塞其他session的写,但是不会阻塞其他session的读。
3、写锁会阻塞其他session的读写。
表上加读锁:
操作 | 当前session(加锁的session) | 其他session |
---|---|---|
读加锁的表 | 能 | 能 |
读其他表 | 不能(解锁之后才能,加锁的时候会报错) | 能 |
写加锁的表 | 不能 | 会阻塞,但是锁一旦释放之后,就立刻执行 |
写其他表 | 不能 | 能 |
表上加写锁:
操作 | 当前session(加锁的session) | 其他session |
---|---|---|
读加锁的表 | 能 | 不能 |
读其他表 | 不能(解锁之后才能,加锁的时候会报错) | 能 |
写加锁的表 | 不能 | 会阻塞,但是锁一旦释放之后,就立刻执行 |
写其他表 | 不能 | 能 |
注意: myisam的读写锁调度是写锁比读锁优先。写锁后,其他线程不能对该表做任何操作,会阻塞在那边,如果大量的更新操作会让读操作很难拿到锁,严重的时候会使读操作永久阻塞,这就是为什么myisam不适合做大量写操作业务数据库的引擎。
演示:
1、准备工作: 创建一张存储引擎为myisam的test02表。
2、关闭自动提交:
set autocommit=0;
show variables like 'autocommit';
3、给test02表加一个读锁
给test02表加一个读锁:lock table 表名 read(write);
查看当前加锁的表:show open tables where in_use>0;
4、结论1:表上加读锁,所有session都能查询
5、结论2:表上加读锁,当前session无法对表进行编辑(增删改),其他session对表进行编辑会阻塞(右边阻塞了)
6、结论3:表上加读锁,当前session是无法操作其他表,其他session可以操作其他表
Table ‘test01’ was not locked with LOCK TABLES 从字面上的意思是test01不是被锁的表,可以从两个方面去考虑,是不是把test01也锁了就能操作了,还是说当前锁的不是test02而不是test01所以才不能操作。
补充:个人猜想,当前session只能锁一张表,如果锁了一张表之后又去锁另一张表,会释放前者,锁后者。
7、表上加写锁: 在加锁之前必须要保证其他session所有的编辑都提交了,不然会阻塞。
8、结论4:表上加写锁,当前session未编辑的时候,其他session是可以查询的,但是当前session编辑之后未提交事务,其他session对锁定的表进行操作就会阻塞,直到锁被释放之后才能操作出来。
9、结论5:表上加写锁,当前session可以对锁定的表进行增删改查,但是不能对其他表进行操作。
10、结论6:表上加写锁,当前session可以对锁定的表进行编辑之后,不提交事务,然后直接释放锁,默认好像是直接提交了事务(开头是将自动提交事务关闭的)。
11:分析表锁定:show status like 'table%';
Table_locks_immediate:表示可以立即获取锁的查询次数,每立即获取锁,这个值就加一。
Table_locks_waited:表示不能立即获取锁的次数,如果不能立即获取所(即需要等待的话),这个值就加一。这个值往往是反应并发量的关键,如果值越大,则并发量越大(因为等待了很多次)。