事务的ACID是指事务拥有的4个特性的首字母组合:atomicity(原子性), consistency(一致性), isolation(隔离性)和durability(持久性)。
①atomicity(原子性):表示事务是一个不可分割的工作单元,要么在提交事务后所有更改成功,要么在回滚事务时撤消所有更改,不可以只执行其中的一部分操作。
②consistency(一致性):在每次提交、回滚之后或正在进行的事务,数据库始终保持一致状态。如正在跨多个表更新相关数据,则查询看到的将是所有旧值或所有新值,而不是新值和旧值的混合。
③isolation(隔离性):事务在进行过程中相互隔离,他们不能互相干扰,也不能看到彼此的未提交数据。但可以通过修改隔离级别,查看其他事务正在处理的数据。
④durability(持久性):事务提交成功后,该事务所做的更改将会保存在数据库中。
当事务读取另一个事务已修改的数据时,可能会发生dirty read(脏读)、non-repeatable read(不可重复读)和phantom read(幻读)之类的现象。
①dirty read(脏读):当前事务读取了另一个事务已更新但尚未提交的数据。后果就是另一个事务回滚了,此数据就为错误的无效数据。
②non-repeatable read(不可重复读):当前事务读取相同数据2次的过程期间,另一个事务修改了此数据并提交,造成当前事务读取的2次结果不一致。
③phantom read(幻读):当前事务读取相同数据2次的过程期间,另一个事务插入了新行或更新一行以此造成当前事务读取的2次结果不一致。看上不可重复读与幻读两者差不多,但不可重复读偏向于行的修改,幻读偏向于行的新增。
隔离级别是一种用于在多个事务同时进行更改和执行查询时修改事务隔离性(isolation)的设置,权衡事务的保护以提高性能和并发性。
InnoDB储存引擎支持的隔离级别有(从低到高): READ UNCOMMITTED(未提交读)、 READ COMMITTED(已提交读)、REPEATABLE READ(可重复读) 和 SERIALIZABLE(可串行话)。
3.1 READ UNCOMMITTED(未提交读)
说明:为最低的隔离级别,表示当前事务可以读取其他事务已修改但未提交的数据。这个级别会导致很多问题,通常,具有此隔离级别的事务仅执行查询,而不执行插入,更新或删除操作。
3.2 READ COMMITTED(已提交读)
说明:事务无法看到来自其他事务未提交的数据,简单来讲一个事务从开始直到提交前,所做的任何修改对其他事务而言是不可见的。
3.3 REPEATABLE READ(可重复读)
说明:InnoDB的默认隔离级别。保证了在同一个事务内多次读取同样的记录的结果为一致。
3.4 SERIALIZABLE(可串行化)
说明:为最高的隔离级别,表示事务一个接一个的串行执行,访问同一资源时,后面的事务必须等待前面的事务操作完成后才能进行操作。
4.1 关系
不同的隔离级别解决脏读、不可重复读和幻读的问题也不一样,关系如下:
隔离级别 | dirty read(脏读) | non-repeatable read(不可重复读) | phantom read(幻读) |
READ UNCOMMITTED(未提交读) | 未解决 | 未解决 | 未解决 |
READ COMMITTED(已提交读) | 已解决 | 未解决 | 未解决 |
REPEATABLE READ(可重复读) | 已解决 | 已解决 | 未解决 |
SERIALIZABLE(可串行化) | 已解决 | 已解决 | 已解决 |
4.2 已提交读与可重复读的区别
两者的主要区别在于不可重复读的策略。
例如事务A读取了2次行R1,在读取2次期间事务B对行R1进行了修改,那么:
当隔离级别为READ COMMITTED(已提交读)时:事务A读取2次行R1的数据不一样。
当隔离级别为REPEATABLE READ(可重复读)时:事务A读取2次行R1的数据一样。
脏读、不可重复读和幻读:https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_read_phenomena
隔离级别:https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_isolation_level