本文主要介绍数据库的事务和锁,内容包括:
数据库事务和级别 事务的四大特性(ACID)数据库事务级别事务级别的使用脏读、不可重复读、幻读 保障数据库事务的锁 读锁、写锁、共享锁(S锁)、独占锁(X锁)、意向共享锁(IS)、意向排他锁行锁、表锁、页锁悲观锁、乐观锁锁的本质释放锁共享或排他锁的三种形式 非锁 MVCC 死锁 死锁示例死锁产生原因读锁、写锁、共享锁(S锁)、独占锁(X锁)、意向共享锁(IS)、意向排他锁(IX)
读锁: 允许多个事务对同一个数据进行读操作。示例:lock table xxx read 写锁: 排他锁,只能允许一个事务进行操作。示例:lock table xxx read 读写锁的升级关系(也是产生死锁的原因) 读锁无法升级为写锁写锁可以降级为读锁 共享锁: 类似读锁。示例:SELECT * FROM table_name WHERE … LOCK IN SHARE MODE 独占锁: 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X)示例:SELECT * FROM table_name WHERE … FOR UPDATE 意向共享锁:事务在给一个数据行加共享锁前必须先取得该表的IS锁。意向排他锁:事务在给一个数据行加排他锁前必须先取得该表的IX锁行锁、表锁、页锁(锁的粒度)
锁定数据库的行、表、页等模块,不同的数据库,不同的引擎时下形式不同。悲观锁、乐观锁
利用时间戳等,通过不停的对比来更新数据的,是乐观锁。加独占锁,就是悲观锁,比如for update。锁的本质
锁的本质是锁索引,锁的是聚簇索引, InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!存在主键的话是主键索引不存在主键的话,是锁_row索引,因此会造成行锁升级为表锁释放锁
显示加锁后,使用unlock隐式加锁后,使用回滚(rollback)或者提交(commit)共享或排他锁的三种形式
Record lock 锁的时候,只锁特别的记录 Gap lock 锁住记录的间隙 Next-Key Locks 除了锁住记录本身,还要再锁住索引之间的间隙参考博客
MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)理解innodb的锁(record,gap,Next-Key lock)多版本并发控制的思想就是保存数据的历史版本,通过对数据行的多个版本管理来实现数据库的并发控制。这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需要加锁也可以保证事务的隔离效果
快照读和当前读
快照读 SELECT * FROM t WHERE id=1 当前读 SELECT * FROM t WHERE id=1 LOCK IN SHARE MODE; SELECT * FROM t WHERE id=1 FOR UPDATE; 参考博客:MVCC多版本并发控制