基本命令
查看那张表被锁住,其中In_use字段大于0则表被锁。
show open tables;
给某张表上锁
lock table 【表名】【read/write】;
释放所有的锁
unlock tables;
查看引擎
show engines;
查看自动提交状态
show variables like 'autocommit';
表锁
以下是在MyISAM引擎下,MyISAM偏读。
准备
- t_logs 表一张。
- session1 给t_logs上读锁或写锁。
- session2 不做任何与锁有关操作。
读锁
读锁也叫共享锁。
Session1 | Session2 |
---|---|
可以查询 t_logs 表 | 可以查询 t_logs 表 |
不可以更新 t_logs 表 | 不可以更新 t_logs 表 会阻塞,必须等待锁释放 |
不可以查询别的表 | 可以查询别的表 |
不可以更新别的表 | 可以更新别的表 |
总结:当前会话为某张表加了读锁,当前会话仅仅能读取加锁的表,任何其它操作都不能做。而其他会话对此表只有读的权限,但除此之外的表,则正常操作。
写锁
写锁也叫排它锁。
Session1 | Session2 |
---|---|
可以查询 t_logs 表 | 不可以查询 t_logs 表 会阻塞 |
可以更新 t_logs 表 | 不可以更新 t_logs 表 会阻塞,必须等待锁释放 |
不可以查询别的表 | 可以查询别的表 |
不可以更新别的表 | 可以更新别的表 |
总结:当前会话为某张表加了写锁,那么当前会话就独享了这张表,拥有这张表的读写权限,且不能够对除此表之外的任何表做任何操作。其它会话也不可以对此表进行任何操作。
行锁
行锁演示是在InnoDB引擎下,该引擎支持事务,并且为了并发性能引进了行级锁。上行锁的方式有两种:
- select * from t_logs where id = 1 for update 其中增删改操作自动上行锁,相当于上了写锁(排它锁)。
- select * from t_logs where id = 1 lock in share mode 相当于上了读锁(共享锁)。
准备说明
为了演示效果,先关闭自动提交功能或者也可以手动开启事务。
set autocommit = 0 或者 begin
步骤
- 开启session1
- set autocommit = 0
- update t_logs set name = 'lisi' where id = '1';
- 开启session2
- set autocommit = 0
- 读取、修改 id = 1 的这条记录
结论
在Session1执行 commit 命令之前,假设修改 id = 1 的这一行,得出如下结论:
Session1 | Session2 |
---|---|
能够修改id为1的这一行 | 除了id为1的这一行都可以修改 |
也能够修改别的记录 但修改哪条记录,那条记录就被锁住 |
除了被锁住的记录不能修改以外(可以读),其它都可以修改 |
总结:行级锁顾名思义就是锁定数据库中的一行或者符合where
条件的某些行,对于数据库来说开销比锁一张表大,但是发生锁冲突的概率比表锁小很多,并发性能高很多,当前会话锁住这一行后,其它会话要想修改这一行,必须等待上一个会话进行事务的提交,否则就会阻塞在这里。但对于其它未被锁住的行,是不受任何影响的。
间隙锁
什么时候会发生间隙锁?看下面例子:
mysql> select * from t_permission;
+----+----------------+-------------+
| id | url | description |
+----+----------------+-------------+
| 1 | /user/create | create |
| 3 | /user/update | update |
| 4 | /user/retrieve | retrieve |
| 5 | /user/delete | delete |
+----+----------------+-------------+
t_permission 表 id 为主键,但缺少了 id = 2,当我们使用范围更新数据的时候,如下语句:
update t_permission set description = '666' where id > 0 and id < 6;
将 id = 2 包括了进去,那么mysql默认的会将这个范围之内所有的连续id都上锁,与此同时,在另一个会话中进行插入 id = 2 的数据操作:
insert into t_permission values(1,'222','222');
那么这个插入操作会阻塞,这就是间隙锁。如果线上环境发生了这样的锁等待,很不好发觉,可以用show profile命令来排查。