2021-06-30 09:39:52来源:窝游网 作者:窝游网
MySQL的InnoDB存储引擎行锁是加在索引上的,所以只当增删改查操作是通过索引找到指定数据行的时候,才能对相应数据行的索引加锁,否则只能对整个表加表锁,表共享读锁或表独占写锁。
当一个事务不经过索引查询数据,即顺序读取(全表扫描)时,先获取表的意向共享锁,然后对表添加共享读锁,阻止其他事务对表的更新,新增和删除操作,但不影响查询操作,共享读锁之间是兼容的。
当一个事务不经过索引更新,删除数据,即全表扫描符合条件的数据行时,先获取表的意向独占锁,然后对表添加独占写锁,在执行更新,删除时阻止其他事务对表的读及写操作。
当一个事务使用索引去查询数据,即随机读取时,先获得表的意向共享锁,然后对符合条件的的索引区间加共享读锁(聚集索引肯定会加锁,若用到了非聚集索引一样加锁),共享读锁之间是兼容的,因此不影响其他事务对被锁数据行的访问。当其他事务想要修改,删除加锁的数据行时,若未使用索引则在获取表独占写锁时会失败。若使用索引检索这些数据行,则可能会在非聚集索引处被阻塞(查询事务和修改事务使用同一个索引检索数据行),也可能在聚集索引处被阻塞(通过非聚集索引查询到聚集索引的键,通过此键查询到相应的聚集索引,同时读到数据航,这是读和写,写和写之间的事务串行化保证),只能等待查询事务释放索引区间的共享读锁,然后执行更新,删除操作。当一个事务想要将新的数据行插入到被加锁的数据行中,也需要等待共享读锁的释放。因为InnoDB实现了间隙锁机制,即当一个事务按一个条件(id < 10,id列含有索引)加锁数据行时,其他事务不能在锁释放前将符合此条件的数据行(id = 5)插入到表中,此机制一定程度防止了幻读的出现。猜测实现机制:前一个事务对数据行的索引加了锁(聚集索引和非聚集索引),其他的事务插入数据时,需要新增聚集/非聚集索引,但是此时符合条件的聚集/非聚集索引区间已经被加锁,不能实时插入索引,需要等到索引区间的锁被释放,这个可能是间隙锁的实现原理。
当一个事务通过索引去更新,删除数据行时,先获取表的意向排他锁,然后对符合条件的数据行的索引加锁(聚集/非聚集),阻止其他事务对被锁数据行的读,写。同理实现间隙锁。