上锁后,整个数据库处于只读状态
flush tables with read lock
释放:?
unlock tables
应用:用于全库逻辑备份
缺点:如果数据量很大,备份会花很多时间,只能读数据,造成业务停滞
如果引擎支持可重复读的隔离级别,备份之前可以先开启事务,且由于MVCC的支持,备份期间数据库仍然可以更新。?
分为共享锁和独占锁,会互斥
//表级别的共享锁,也就是读锁;
lock tables t_student read;
//表级别的独占锁,也就是写锁;
lock tables t_stuent write;
?释放:
unlock tables
尽量避免使用InnoDB中的表锁,因为还有颗粒度更细的行级锁。
不需要显示使用MDL,对表操作时,会自动加MDL。
MDL是为保证用户执行CRUD操作时,防止其它线程对表结构做变更。
MDL在事务执行期间,一直持有,事务提交后释放。
MDL写锁获取优先级高于读锁,当写锁等待,后续所有CRUD操作都会被阻塞。因此,对表结构变更前,要先看看数据库中的长事务是否加了MDL读锁,如果加了读锁,后面所有操作都会被阻塞。可以考虑kill掉这个长事务。
select 可以对记录加共享锁和独占锁,加锁之前,先对表加意向锁。
//先在表上加上意向共享锁,然后对读取的记录加共享锁
select ... lock in share mode;
//先表上加上意向独占锁,然后对读取的记录加独占锁
select ... for update;
也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。
意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)发生冲突。
作用:如果没有意向锁,加独占表锁时,就需要遍历表中所有记录,查看是否有记录存在独占锁。而有意向锁后,在对记录加独占锁之前,会对表加上意向独占锁,和独占表锁互斥。
主键字段声明AUTO_INCREMENT属性,可以不指定主键的值,实现自增。这是通过AUTO-INC锁实现的。
AUTO-INC锁是一种特殊的表锁,不再是一个事务提交后释放,而是执行完插入语句后就会释放。
插入数据,会加一个表级AUTO-INC锁,主键自增,其它插入语句会被阻塞,保证字段的值连续递增;插入完毕,锁释放。
但大量数据插入时,会影响性能。因此,InnoDB提供了一种轻量级的锁来实现递增。插入数据时,给主键字段赋值完毕后,锁就释放,不需要等整个插入语句执行完毕。
轻量级锁可能会导致主从数据库不一致的问题。参考小林coding.
InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。
普通的 select 语句是不会对记录加锁的,因为它属于快照读。
如果要在查询时对记录加行锁,如下,这种查询会加锁的语句称为锁定读。对记录加锁前,会对表先加意向锁。
//对读取的记录加共享锁
select ... lock in share mode;
//对读取的记录加独占锁
select ... for update;
记录锁,分为S锁和X锁。
共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。
间隙锁,只存在于可重复读隔离级别,解决幻读现象。
假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。
间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是并没有什么区别,间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的。
临键锁,Record Lock + Gap Lock,锁定一个范围,并锁定记录本身。
假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。
next-key lock 是包含间隙锁+记录锁的,如果一个事务获取了 X 型的 next-key lock,那么另外一个事务在获取相同范围的 X 型的 next-key lock 时,是会被阻塞的。
事务插入一条记录,需要判断插入位置是否被其他事务加了间隙锁。有的话,就会阻塞,直到有间隙锁的事务提交为止,在此期间,会形成一个插入意向锁,表示想插入记录,但处于等待状态(MySQL 加锁时,是先生成锁结构,然后设置锁的状态,如果锁状态是等待状态,并不是意味着事务成功获取到了锁,只有当锁状态为正常状态时,才代表事务成功获取到了锁)。
插入意向锁并不是意向锁,是一种特殊的间隙锁,锁住的是一个点,而不是一个区间。
两个事务不能在同一时间内,一个拥有间隙锁,一个拥有间隙区间内的插入意向锁。