索引
- 按数据结构分类:B+tree索引、Hash索引、Full-text索引
- 按物理存储分类:聚簇索引(主键索引)、二级索引(辅助索引)
- 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引
- 按「字段个数」分类:单列索引、联合索引
锁
大致所有层级和目的的锁都有共享锁和排他锁,不再单独列出。
全局锁
flush tables with read lock
指令手动触发,使整个数据库处于只读的状态。
表级锁
- 表锁
加表共享锁:lock tables table_name read
加表排他锁:lock tables table_name write
- 元数据锁
元数据锁不需要手动使用,它的作用是防止数据库执行操作期间表的结构被修改 - 意向锁
意向锁的目的是为了快速判断表里是否有记录被加锁(避免在并需要锁定全表时,遍历表中所有的记录,检查是否有某些记录上存在记录级别的锁)。
Mysql 执行插入、更新、删除操作,会先对表加上意向独占锁,然后对该记录加独占锁。
普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。也可以通过特殊命令对 select 加锁
//先在表上加上意向共享锁,然后对读取的记录加共享锁
select ... lock in share mode;
//先表上加上意向独占锁,然后对读取的记录加独占锁
select ... for update;
- AUTO-INC 锁
AUTO-INC 锁是特殊的表锁机制,锁不是再一个事务提交后才释放,而是再执行完插入语句后就会立即释放。
在插入数据时,会加一个表级别的 AUTO-INC 锁,然后为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等插入语句执行完成后,才会把 AUTO-INC 锁释放掉。
那么,一个事务在持有 AUTO-INC 锁的过程中,其他事务的如果要向该表插入语句都会被阻塞,从而保证插入数据时,被 AUTO_INCREMENT 修饰的字段的值是连续递增的。
行级锁
- 记录锁
- 间隙锁
只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。
间隙锁的锁定对象是两个相邻记录之间的”间隙“,在其他事务在获取间隙锁之前不能在这两个记录之间插入,或者删除这两个记录中的任何一个,这两种行为都因为会改变”间隙“而被间隙锁阻塞。
同时使用多个间隙锁则可以锁定一段区间 - NextKey 锁(记录锁 + 间隙锁)
同时锁定间隙和记录,使其他事务既无法在这个区间增加或删除记录,也无法修改记录 - 插入意向锁
插入意向锁是在插入一条记录行前,由 INSERT 操作产生的一种间隙锁。该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。假设存在两条值分别为 4 和 7 的记录,两个不同的事务分别试图插入值为 5 和 6 的两条记录,每个事务在获取插入行上独占的(排他)锁前,都会获取(4,7)之间的间隙锁,但是因为数据行之间并不冲突,所以两个事务之间并不会产生冲突(阻塞等待)。