1.乐观锁与悲观锁
乐观锁
不主动加锁,而是在更新前通过校验来判别数据是否被修改。一般通过数据版本(version)记录机制实现,数据行增加 version 字段,每次更新数据都更新对应 version。当读取数据时,version 字段一同取出,提交更新时对比数据行当前 version 是否与之前一致,如果一致则表明数据可进行更新操作,如不一致则认为数据为过期数据,不予更新。
悲观锁
认为每次操作都会存在数据冲突,所以每次操作时,都需要主动获取锁才能对数据进行操作。悲观锁由数据库内部实现,调用相关语句即可。
共享锁与排他锁
共享锁与排他锁都属于悲观锁的范畴,是悲观锁的不同实现。
共享锁
共享锁,俗称读锁(read lock),是由读取操作创建的锁。所有用户可同时获取共享锁,并发读取数据,但是任何事务都不能对该数据进行修改(即获得排他锁)直至共享锁全部被释放。如果事务对加了读锁的数据进行写操作,很可能造成死锁。排他锁
排他锁,俗称写锁(write lock),会阻塞其他所有排他锁与共享锁。某一事务对一行数据加上排他锁,则其他事务不能对该行进行读写操作,在此事务结束前,其他事务不能堆该行加任何锁。
2.行锁与表锁
行锁
Innodb 基于索引实现行锁,实质上是针对索引加锁而不是针对数据记录加锁,在加锁期间若索引失效,行锁会升级成表锁。
表锁
Innodb 与 MyISAM 均支持表锁,Innodb 在不通过索引检索数据时,会使用表锁。
3.MVCC(Multi-Version Concurrency Control:多版本并发控制)
MVCC,即同一份数据临时保留多版本的一种方式,进而实现并发控制。在MySQL中建表时,每个表都会有三列隐藏记录,跟MVCC相关的有:数据行的版本号(DB_TRX_ID)、删除版本号 (DB_ROLL_PT)。
MVCC-insert
执行插入操作时,将全局事务ID写入 DB_TRX_ID。
MVCC-delete
执行删除操作时,数据并没有被真正删除,而是全局事务ID记录至 DB_ROLL_PT。
MVCC-update
复制当前记录行A的副本到一条新的记录B,B中 DB_TRX_ID 置为 A 的 DB_ROLL_PT。
MVCC-select
查找数据行版本号小于当前事务版本号、删除版本号要么为 NULL 要么大于当前事务版本号的数据行记录,确保查询出来的数据行记录在事务开启之前没有被删除。