节选自《MySQL 常见知识点 & 面试题总结》
表级锁和行级锁理解吗?有什么区别?
MyISAM 仅仅反对表级锁 (table-level locking),一锁就锁整张表,这在并发写的状况下性十分差。
InnoDB 不光反对表级锁 (table-level locking),还反对行级锁 (row-level locking),默认为行级锁。行级锁的粒度更小,仅对相干的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说,InnoDB 的性能更高。
表级锁和行级锁比照 :
- 表级锁: MySQL 中锁定粒度最大的一种锁,是针对非索引字段加的锁,对以后操作的整张表加锁,实现简略,资源耗费也比拟少,加锁快,不会呈现死锁。其锁定粒度最大,触发锁抵触的概率最高,并发度最低,MyISAM 和 InnoDB 引擎都反对表级锁。
- 行级锁: MySQL 中锁定粒度最小的一种锁,是针对索引字段加的锁,只针对以后操作的记录进行加锁。行级锁能大大减少数据库操作的抵触。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会呈现死锁。
行级锁的应用有什么注意事项?
InnoDB 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当咱们执行 UPDATE
、DELETE
语句时,如果 WHERE
条件中字段没有命中索引或者索引生效的话,就会导致扫描全表对表中的所有记录进行加锁。这个在咱们日常工作开发中常常会遇到,肯定要多多留神!!!
不过,很多时候即应用了索引也有可能会走全表扫描,这是因为 MySQL 优化器的起因。
共享锁和排他锁呢?
不论是表级锁还是行级锁,都存在共享锁(Share Lock,S 锁)和排他锁(Exclusive Lock,X 锁)这两类:
- 共享锁(S 锁):又称读锁,事务在读取记录的时候获取共享锁,容许多个事务同时获取(锁兼容)。
- 排他锁(X 锁):又称写锁 / 独占锁,事务在批改记录的时候获取排他锁,不容许多个事务同时获取。如果一个记录曾经被加了排他锁,那其余事务不能再对这条事务加任何类型的锁(锁不兼容)。
排他锁与任何的锁都不兼容,共享锁仅和共享锁兼容。
S 锁 | X 锁 | |
---|---|---|
S 锁 | 不抵触 | 抵触 |
X 锁 | 抵触 | 抵触 |
因为 MVCC 的存在,对于个别的 SELECT
语句,InnoDB 不会加任何锁。不过,你能够通过以下语句显式加共享锁或排他锁。
# 共享锁
SELECT ... LOCK IN SHARE MODE;
# 排他锁
SELECT ... FOR UPDATE;
意向锁有什么作用?
如果须要用到表锁的话,如何判断表中的记录没有行锁呢?一行一行遍历必定是不行,性能太差。咱们须要用到一个叫做意向锁的东东来疾速判断是否能够对某个表应用表锁。
意向锁是表级锁,共有两种:
- 动向共享锁(Intention Shared Lock,IS 锁):事务有动向对表中的某些加共享锁(S 锁),加共享锁前必须先获得该表的 IS 锁。
- 动向排他锁(Intention Exclusive Lock,IX 锁):事务有动向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先获得该表的 IX 锁。
意向锁是有数据引擎本人保护的,用户无奈手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。
意向锁之间是相互兼容的。
IS 锁 | IX 锁 | |
---|---|---|
IS 锁 | 兼容 | 兼容 |
IX 锁 | 兼容 | 兼容 |
意向锁和共享锁和排它锁互斥(这里指的是表级别的共享锁和排他锁,意向锁不会与行级的共享锁和排他锁互斥)。
IS 锁 | IX 锁 | |
---|---|---|
S 锁 | 兼容 | 互斥 |
X 锁 | 互斥 | 互斥 |
《MySQL 技术底细 InnoDB 存储引擎》这本书对应的形容应该是笔误了。
InnoDB 有哪几类行锁?
MySQL InnoDB 反对三种行锁定形式:
- 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁。
- 间隙锁(Gap Lock):锁定一个范畴,不包含记录自身。
- 临键锁(Next-key Lock):Record Lock+Gap Lock,锁定一个范畴,蕴含记录自身。记录锁只能锁住曾经存在的记录,为了防止插入新记录,须要依赖间隙锁。
InnoDB 的默认隔离级别 REPEATABLE-READ(可重读)是能够解决幻读问题产生的,次要有上面两种状况:
- 快照读 :由 MVCC 机制来保障不呈现幻读。
- 以后读 :应用 Next-Key Lock 进行加锁来保障不呈现幻读。