MySQL中的锁
为什么Mysql默认的事务隔离级别是可重复读?
——因为在早期的数据库主从复制的过程中复制的binlog数据传输采用的是statement,即传输的是SQL语句,在读未提交和读提交两种情况下,会将先不同的事务数据合并,比如先进行了删除但是没有提交,后面又进行了插入但是先提交,然后删除才提交,这样的话他就会合并到一起,把插入的也删除了。所以为了解决这个问题,就采用默认的可重复读,这个隔离级别下会默认添加间隙锁和临键锁,事务间会进行阻塞。
MySQL有哪些锁类型?
——S锁和X锁,这是MySQL锁的两个基本大类,S锁即共享锁,运行多个事务同时获得,X锁即排他锁,只允许一个事务获得,其他事务被阻塞。这两种锁在查询语句中也可以实现:
SELECT ... FOR UPDATE
:X锁,用于在当前事务中锁定所查询的行,并且锁定这些行之间的间隙,防止其他事务插入或删除这些记录。
SELECT ... LOCK IN SHARE MODE
:S锁,类似于 FOR UPDATE
,但允许其他事务读取这些行,而不允许修改或插入新的行。
——元数据锁(读锁、写锁),即当事务会改变元数据(表的结构信息及相关的配置信息)时,就会获取元数据锁。
当DDL操作会修改到表的元数据时,会获取写锁,阻塞其他事务同时修改元数据。
当DML操作时会获取读锁,防止同时其他DDL事务修改元数据。
——意向锁(IS锁、IX锁),当要对表进行上锁的时候,如果此时表里有行锁,那么表锁和行锁就会冲突,为了避免这种情况,就出现了意向锁。
IS锁:共享意向锁,当需要对表中的某条数据加上S锁的时候,先在表上加上一个IS锁,表明这张表内有S锁,如果后续要继续在这个表上S锁就可以上,而如果是X锁因为和S锁冲突,所以就不能上。
IX锁:共享独占锁,和IS锁同理,后续要上S锁或者X锁时都无法上,因为X锁是排他的。
元数据锁和意向锁都属于表锁。
——记录锁,记录锁会锁住索引,由于MySQL中即使不显式地添加索引,也会默认添加聚簇索引,即使没有主键也会创建隐藏的聚簇索引。所以记录锁会锁住索引字段来防止索引字段被修改。但是如果查询的条件不是索引,记录锁就会不只锁住索引字段,而是锁住所有字段,那么修改任何字段都会被阻塞。所以没有索引的列不建议轻易加锁。注意:记录锁并不只是在查询的时候生效,增删改以及加锁查都会生效。
——间隙锁和临键锁,这是MySQL在可重复读级别用来防止幻读而自动采用的两种锁,即会锁住数据行之间的间隙,例如在可重复读下,另一个事务在id为1和3之间插入一条id为2的数据,就会被阻塞,以此避免幻读发生。
——插入意向锁,当插入数据被间隙锁和临键锁阻塞后就会获得插入意向锁,以此表明自己处于等待间隙锁释放的状态。
记录锁、间隙锁和临键锁、插入意向锁都属于行锁。
——Auto-Inc Lock,这是一个特殊的表级锁,当插入数据时会获取这个锁然后进行自增字段的自增,自增结束后释放锁。在MySQL5.1.22版本之后又添加了一个互斥量,性能高于Auto-Inc Lock,之后MySQL添加了一个innodb_autoinc_lock_mode配置,当值为0是只用Auto-Inc Lock,当值为1(默认值)如果插入行数已知就用互斥量,否则用Auto-Inc Lock,当值为2时只用互斥量。