Mysql 事务及 MVCC 详解
ACID 四大特性
-
原子性(atomicity)
一个事务操作看做一个做小的执行单元,里面的所有操作要么全部成功提交,要么全部失败回滚。 -
一致性(consistency)
数据库总是从一个一致性的状态转换为另一个一致性状态,比如 A 给 B 转账 200元,最终一致性则操作完成后保证 A 的账户余额少了 200,B 多了 200。 -
隔离性(isolation)
事务之间相互隔离,事务里面所做的修改都是互不可见。 -
持久性(durability)
事务提交后,所做的修改就会永久的持久化到磁盘上。
Mysql 提供了2中支持事务的引擎,InnoDB 和 NDB Cluster,我们这里主要介绍 InnoDB。
mysql 默认开启自动提交事务模式,意思就是当我们执行单个的 CURD 的时候,都会伴随着一次 start 和 commit;
show variables like 'AUTOCOMMIT' // 查看事务的开启状态
从这里就能看出,如果我们的系统对于事务的要求并不高的话,可以选择使用MyISAM 存储引擎会减少系统的很多开销,需要做事务处理的地方我们再利用锁来完成。
事务的隔离级别
SQL 标准规范定了以下几种隔离级别,较低级别的隔离开销更小,支持并发更高。隔离级别由高到低依次是,串行、可重复读、提交读、未提交读
-
READ UNCOMMITTED(未提交读)
事务可以看见其它事务未提交的数据,会产生脏读,一般都不会选择使用该级别 -
READ COMMITTED(提交读)
事务可以看见其它事务已经提交的数据,会产生不可重复读,幻读,大多数数据库默认隔离级别是它,但是 Mysql 不是。 -
REPEATABLE READ(可重复读)
它解决了脏读问题,解决了不可重复读问题,但是还存在幻读的情况。Mysql 采用了多版本 MVCC 来解决了幻读的问题。等等会详细的分析这个隔离级别。 -
SERIALIZABLE(串行化)
强制事务串行执行,会导致大量锁的竞争请求超时等情况,一般不选用这个级别。
在讲解 Mysql 的默认隔离级别 REPEATABLE READ(可重复读) 之前,我们先来了解一下
-
脏读
这个比较简单,就是事务可以看见其它事务未提交的数据,如果某个事务最后回滚了,其它事务又拿来做业务处理了肯定是错误的。一般 未提交读 才会产生这个情况,而我们几乎不会选择使用这个隔离级别。 -
不可重复读
这是大多数数据库默认的隔离级别,它的性能好于可重复读,但是会产生一个情况就是他在整个事务的处理时间段查询道的数据可能是不一样的。比如 A 在 T1 - T10 时刻处理该事务,T3 查询到 user age = 25; 此时另外一个用户 B 开启一个事务 T2 - T4时间段修改了 user age = 28; 那么这种情况下,A 在 T5 之后查询到的数据 age = 28; 和 T3 时刻读取到的数据不一致了。这就是不可重复读,不可重复读在某些场景下也是允许的,所以才会作为其它数据库默认的隔离级别,具体的选用看实际情况,但是Mysql 一般使用的都是其默认的隔离级别。 -
幻读
当某个事务在读取某个范围内的数据时候,其它事务又在该范围插入了一条数据,之前的事务再次读取的时候就会产生幻行(也就多了一条数据)。
网友评论