原子性(Atomicity):
个事务必须被视为一个不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
一致性(Consistent):
数据库总是从一个一致性的状态转换到另外一个一致性的状态.
隔离性(Isolation):
一个事务所做的修改在最终提交以前,对其他事务是不可见的
持久性(Durable):
一旦事务提交,则其所做的修改就会永久保存到数据库中。
READ UNCOMMITTED(未提交读),
在 READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read),这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。
READ COMMITTED(提交读)
大多数数据库系统的默认隔离级别都是READ COMMITTED(但MySQL不是)。一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫不可重复读(nonrepeatable read),有可能出现幻读(Phantom Read),
REPEATABLE READ(可重复读)
REPEATABLE READ 解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。 所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
SERIALIZABLE(可串行化)
SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了上面说的幻读问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。
隔离级别 | 读一致性 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
---|---|---|---|---|---|
未提交读(Read Uncommitted) | 最低级别 | 是 | 是 | 是 | 否 |
已提交读(Read Committed) | 语句级别 | 否 | 是 | 是 | 否 |
可重复读(Repeatable Read) | 事务级别 | 否 | 否 | 是 | 否 |
串行化(Serializable) | 最高级别,事务级 | 否 | 否 | 否 | 是 |
MySQL的大多数的事务型存储引擎实现的都不是简单的行级锁,基于提升并发性能的考虑,都引入了多版本并发控制技术(MVCC),可以认为MVCC是行级锁的一个变种,在很多情况下可以避免加锁的操作,让开销更低。InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。一个保存的行的创建时间,一个保存行过期时间(或删除时间)。存储的不是实际的时间值,是系统的版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本的版本号,用来和查询列的每行记录的版本号进行比较。
MVCC只在已提交读(Read Committed)和可重复读(Repeatable Read)两个隔离级别下工作,其他两个隔离级别和MVCC是不兼容的。因为未提交读,总数读取最新的数据行,而不是读取符合当前事务版本的数据行。而串行化(Serializable)则会对读的所有数据多加锁,下面以可重复读(Repeatable Read)为例子,说明下以select、delete、 insert、 update语句MVCC具体是如何操作的。
SELECT
Innodb检查每行数据,确保他们符合两个标准:
1、InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行
2、行的删除操作的版本一定是未定义的或者大于当前事务的版本号,确定了当前事务开始之前,行没有被删除符合了以上两点则返回查询结果。
INSERT
InnoDB为每个新增行记录当前系统版本号作为创建ID。
DELETE
InnoDB为每个删除行的记录当前系统版本号作为行的删除ID。
UPDATE
InnoDB复制了一行。这个新行的版本号使用了系统版本号。它也把系统版本号作为了删除行的版本。