Mysql设计了事务隔离机制、锁机 制、MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题。
事务及其ACID属性
- 原子性(Atomicity):在一个事务中,只有一个原子单元对其作修改,要么全部完成,要么全部失败。
- 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规 则都必须应用于事务的修改,以保持数据的完整性。
- 隔离性(Isolation) :在一个事务中,一条数据多次查询的情况下必须是唯一的,不受外界干扰。
- 持久性(Durable) :事务完成后,数据必须是持久化的,不受机器宕机的影响。
并发事务会出现哪些问题:
- 脏写:一个事务在另一个数据改数据后,并不知道其他事务已经改过而覆盖写的问题。
- 脏读:一个事务修改数据后未提交,另一个数据读取了该数据,然后第一个事务出现回滚。
- 不可重读:一个事务中读取相同数据出现了不同的结果。
- 幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据。
事务隔离级别
常看当前数据库的事务隔离级别: show variables like 'tx_isolation';
设置事务隔离级别:set tx_isolation='REPEATABLE-READ';
MVCC多版本并发控制机制
基于undo日志和read view机制。
read view生成规则:事务创建时会生成一个readview[11,12,16]:21,蓝色部分为未完成的事务ID,绿色部分为已生成最大的事务ID。注意:事务ID是以自增的方式生成的。
首先事务ID只在执行更新语句前生成,在读取数据时不会生成。在执行增删改语句时会将改后的数据生成一个链式的undo日志。然后和readview进行比对进行取值,具体规则:
锁分类
- 从性能上分为乐观锁(用版本对比来实现)和悲观锁
- 从对数据库操作的类型分,分为读锁和写锁(都属于悲观锁)
读锁(共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响 写锁(排它锁,X锁(eXclusive)):当前写操作没有完成前,它会阻断其他写锁和读锁
- 从对数据操作的粒度分,分为表锁和行锁
表锁:并发度低,一般是数据迁移的时候才会使用
行锁:开销大(需要找到指定行),粒度小,并发度高,锁冲突的概率低。
InnoDB相比于MYISAM(支持事务、支持行级锁)
间隙锁:在可重复读隔离级别下才会生效
自增的ID存在间隙的话插入间隙的值会触发间隙锁,比如:间隙 id 为 (3,10],(10,20],(20,正无穷) 这三个区间
注意:无索引行锁会升级为表锁
update account set balance = 800 where name = 'lilei';
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为 表锁。
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为 表锁。