MySQL锁机制从全局锁到行级锁,哪种更高效?

摘要:全局锁 flush tables with read lock 执行后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞: 对数据的增删改操作,比如 insert、delete、update等语句; 对表结构的更改操作,比如
全局锁 flush tables with read lock 执行后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞: 对数据的增删改操作,比如 insert、delete、update等语句; 对表结构的更改操作,比如 alter table、drop table 等语句。 全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。 但是加上全局锁后,整个数据库都是只读状态,无法更新数据。 因此,一般也不建议用全局锁进行全库逻辑备份。InnoDB支持可重复读的隔离级别,那么在备份数据库之前可以先开启事务,会先创建 Read View,然后整个事务执行期间都在用这个 Read View,而且由于 MVCC 的支持,备份期间业务依然可以对数据进行更新操作。因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。 表级锁 innodb的 表锁,分成意向共享锁 和意向独占锁,表锁是innodb引擎⾃动加的,不⽤⾃⼰加。 意向共享锁:加共享⾏锁时,必须先加意向共享锁; 意向独占锁 :给某⾏加独占锁时,必须先给表加意向独占锁。 insert、update、delete,innodb会⾃动给那⼀⾏加⾏级独占锁。 普通的select啥锁都不加。但是可以手动加锁 //先在表上加上意向共享锁,然后对读取的记录加共享锁 select ... lock in share mode; //先在表上加上意向独占锁,然后对读取的记录加独占锁 select ... for update; 行级锁 InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。 普通的 select 语句是不会对记录加锁的,因为它属于快照读。如果要在查询时对记录加行锁,可以使用下面这两个方式,这种查询会加锁的语句称为当前读。 //对读取的记录加共享锁 select ... lock in share mode; //对读取的记录加独占锁 select ... for update; 共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。 行级锁的类型主要有三类: Record Lock,记录锁,也就是仅仅把一条记录锁上; Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;(左开右开区间) Next-Key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。(左开右闭区间) Record Lock Record Lock 称为记录锁,锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的: 当一个事务对一条记录加了 S 型记录锁后,其他事务也可以继续对该记录加 S 型记录锁(S 型与 S 锁兼容),但是不可以对该记录加 X 型记录锁(S 型与 X 锁不兼容); 当一个事务对一条记录加了 X 型记录锁后,其他事务既不可以对该记录加 S 型记录锁(S 型与 X 锁不兼容),也不可以对该记录加 X 型记录锁(X 型与 X 锁不兼容)。 总而言之,当一个事务对一条记录加了读锁后,其它事务也可读,但不可写;当一个事务对一条记录加了写锁后,其它事务不可读也不可写。 Gap Lock Gap Lock 称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。 假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。 Next-Key Lock Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。 假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录 乐观锁和悲观锁 乐观锁和悲观锁都是针对读(select)来说的。 乐观锁 就是非常乐观,做什么事都往好处想; 对于数据库操作,就认为每次操作数据的时候都认为别的操作不会修改,所以不会加锁,而是通过一个类似于版本的字段来标识该数据是否修改过,在执行本次操作前先判断是否修改过,如果修改过就放弃本次操作重新再来。乐观锁适用于多读的应用类型,这样可以提高吞吐量;乐观锁策略:提交版本必须大于记录当前版本才能执行更新。 乐观锁不是数据库自带的,需要自己去实现。
阅读全文