MySQL-事务
特性
ACID,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
-
原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样;
-
一致性(Consistency):数据库的完整性不会因为事务的执行而受到破坏,比如表中有一个字段为姓名,它有唯一约束,也就是表中姓名不能重复,如果一个事务对姓名字段进行了修改,但是在事务提交后,表中的姓名变得非唯一性了,这就破坏了事务的一致性要求,这时数据库就要撤销该事务,返回初始化的状态。
-
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
-
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?
-
原子性和持久性是通过 redo log (重做日志)来保证的;
-
一致性是通过 undo log(回滚日志) 来保证的;
-
隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
事务隔离级别
-
读未提交(read uncommitted,脏读,不可重复读,幻读),指一个事务还没提交时,它做的变更就能被其他事务看到;
-
读提交(read committed,不可重复读,幻读),指一个事务提交之后,它做的变更才能被其他事务看到;
-
可重复读(repeatable read,幻读),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;
-
串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;
关于脏读,不可重复读,幻读(并行事务问题):
- 脏读:读到其他事务未提交的数据;
- 不可重复读:前后读取的数据不一致;
- 幻读:前后读取的记录数量不一致。
- 注意:要解决幻读现象不建议将隔离级别升级到「串行化」,因为这样会导致数据库在并发事务时性能很差。InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它通过next-key lock 锁(行锁和间隙锁的组合)来锁住记录之间的“间隙”和记录本身,防止其他事务在这个记录之间插入新的记录,这样就避免了幻读现象。
对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过 Read View 来实现的,它们的区别在于创建 Read View 的时机不同:
-
「读提交」隔离级别是在每个 select 都会生成一个新的 Read View,也意味着,事务期间的多次读取同一条数据,前后两次读的数据可能会出现不一致,因为可能这期间另外一个事务修改了该记录,并提交了事务。
-
「可重复读」隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View,这样就保证了在事务期间读到的数据都是事务启动前的记录。
这两个隔离级别实现是通过「事务的 Read View 里的字段」和「记录中的两个隐藏列」的比对,来控制并发事务访问同一个记录时的行为,这就叫 MVCC(多版本并发控制)。