MySQL锁介绍
MySQL表级锁:由MySQL SQL layer层实现。
MySQL的表级锁有两种:表锁、元数据锁(meta data lock,MDL)
MySQL 实现的表级锁定的争用状态变量:
show status like 'table%';
- table_locks_immediate:产生表级锁定的次数;
- table_locks_waited:出现表级锁定争用而发生等待的次数;
表锁有两种表现形式:表共享读锁(table read lock)、表独占写锁(table write lock)。
-- 手动增加表锁:
lock table 表名称 read(write),表名称2 read(write),其他;
-- 查看表锁情况:
show open tables;
-- 删除表锁
unlock tables;
表锁
现有两个表,一个是tuser表,一个是tdep表。
(1)读锁
1.首先给tdep表加读锁
lock table tdep read;
2.查询tuser表,发现不能访问非锁定的表。
lock table tdep read;
3.查询tdep表,是可以查询的。
select * from tdep;
4.修改tdep表,修改阻塞,自行加行写锁。
update tdep set name='部门' WHERE id=1
5.释放表锁。
unlock tables;
6.再次查询tuser表,这时是可以进行查询的。
SELECT * from tuser;
(2)写锁
1.给tdep加写锁。
lock table tdep write;
2.查询tuser表,不能访问非限定表。
select * from tuser;
3.查询tdep表,可以查询。
select * from tdep;
4.对tdep表进行更新操作,是可以执行的。
update tdep set name='部门' where id=2;
5.释放表锁。
unlock tables;
6.再次查询tuser表,是可以查询的。
select * from tuser;
元数据锁
在MySQL5.5版本中加入了MDL,当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁。
行级锁
InnoDB存储引擎实现。
InnoDB的行级锁,按照锁定范围来说,可以分为三种:
记录锁(Record Locks):锁定索引中一条记录。
间隙锁(Gap Locks):锁定记录前、记录中、记录后的行RR隔离级(可重复读)-- MySQL默认隔离级别
Next-Key锁:记录锁 + 间隙锁。
行级锁,按照功能来分,可以分为三种:
共享读锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他写锁(X): 允许获得排他写锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
1.自动加DML。对于update、delete 和insert 语句,InnoDB会自动给涉及数据集加排他锁(X)。
2.手动加。
InnoDB也实现了表级锁,也就是意向锁。意向锁是mysql内部使用的,不需要用户干预的。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
意向锁的主要作用是为了【全表更新数据】时的性能提升,否则在全表更新数据时,需要先检索该表是否某些记录上面有行锁。
共享锁 | 排他锁 | 意向共享锁 | 意向排他锁 | |
共享锁 | 兼容 | 冲突 | 兼容 | 冲突 |
排他锁 | 冲突 | 冲突 | 冲突 | 冲突 |
意向共享锁 | 兼容 | 冲突 | 兼容 | 兼容 |
意向排他锁 | 冲突 | 冲突 | 兼容 | 兼容 |
InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点就意味着:只有通过索引条件检索的数据,InnoDB才使用行级锁,否则InnoDB将使用表锁。
间隙锁:是一个在索引记录之间的间隙上的锁。
间隙锁的作用:保证某个间隙内的数据在锁定情况下不会发生任何变化。
间隙锁防止两种情况:1.防止插入间隙内的数据;2.防止已有数据更新为间隙内的数据。
死锁:两个session互相等待对方的资源释放之后,才能释放自己的资源,造成了死锁。