事务
事务就是一组原子性的Sql语句查询。
事务ACID
原子性(Atomicity)
一个事务必须被视为一个不可被分割的工作单元。整个事务中的所有操作要么全部提交成功,要么全部失败回滚。
一致性(Consistency)
数据库总是从一个一致性的状态转换导另外一个一致性的状态。例如转账业务中,无论事务执行失败或者成功,两个账号的总额保持不变。
隔离性(Isolation)
通常指的是并发环境下,一个事务所做的修改在最终提交以前,对其他事务是不可见的。
持久性(Durablity)
一旦事务提交,则其所做的修改就会永久保存到数据库中。不会因为系统发送崩溃,修改的数据丢失。
隔离级别
SQL 标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统开销也最低。
Mysql 中不同的存储引擎的隔离性不同, Innodb默认的隔离性是 可重复读。
READ UNCOMMITED (未提交读)
事务中的修改,即使没有提交,对其他事务也都是可见的。
这个级别中,事务可以读取未提交的数据 ,这被称为dirty read (脏读)
READ COMMITED(提交读)
事务中的修改,提交前,对于其他事务是不可见的。
这个级别也叫做nonrepeatable read(不可重复读),因为两次执行同样的查询,结果可能不一致。
REPEATABLE READ(可重复读)
可重复读,保证了在同一个事务中多次读取同样的记录结果是一致的。但理论上,无法解决 Phantom Read(幻读)问题。
所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录。之前的事务再次读取该范围的记录时,发现两次读取的记录不一致(如A事务将表中记录某个字段从2全改为1,而B事务此时插入一条字段值为2的数据,当A事务再次查询时,就会产生幻读)。
幻读和不可重复读区别在于,前者是由另一个事务插入和删除造成的,后者由另一个事务的更新造成的。
在Mysql InnoDB存储引擎中 通过多版本控制(MVCC, Multiversion Concurrency Control)解决了幻读问题。
SERIALIZABLE(可串行化)
可串行化,通过强制事务串行执行,避免了前面说的幻读。原理就是会在读取的每一行数据上都加锁。
隔离级别引起的问题
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 |
---|---|---|---|
未提交读 | Yes | Yes | Yes |
提交读 | No | Yes | Yes |
可重复读 | No | No | Yes |
可串行化 | No | No | No |
MVCC (多版本并发控制)
InnoDB的可重复读隔离级别时通过MVCC实现的。
MVCC实现原理 ,是通过在每行记录后面保持两个隐藏的列来实现的。这两个列,一个保存行的创建时间,另一个保存删除时间。真实存储的并不是实际的时间值,而是系统版本号。
每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。
MVCC 具体操作流程
SELECT
a. InnoDB 只查找记录行创建版本号小于当前事务版本的数据行,这样能够保证事务读取的行,妖魔是在事务开始之前已经存在,要么是事务自身插入或者修改过的。
b. 行的删除版本要么未定义,要么大于当前的事务版本号。这样可以保证事务读取到1的行,在事务开始之前未被删除。
INSERT
InnoDB为新插入的每一行保存当前事务版本号作为创建版本号。
DELETE
InnoDB为删除的每一行保存当前事务版本号作为删除版本号。
UPDATE
InnoDB为插入一行新记录,保存当前事务版本号作为创建版本号,同事保存当前系统版本号到原来的行作为删除标识。
事务相关SQL
查询事务隔离级别
select @@tx_isolation
设置当前事务隔离级别
set tx_isolation=’隔离级别名称;’