事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致状态转换为另一种一致状态。
关键词事务四大特性ACID
MySql事务隔离级别
MVCC多版本并发控制实现方式
运行过程
MVCC解决了幻读?
InnoDB解决幻读的方式
事务的分类扁平事务Flat Transactions
带有保存点的扁平事务Flat Transactions with Savepoint
链事务Chained Transaction
嵌套事务Nested Transaction
分布式事务
重做日志redo log
undoinsert undo log
update undo log
group commit
MySQL分布式事务XA事务
两段式提交two-phase commit
1.事务四大特性ACID
原子性Atomicity:
一个事务必须被视为一个不可分割的最小工作单元。(要么全部做要么全部不做)
一致性Consistency:
数据库总是从一个一致性的状态转换到另外一个一致性的状态。(银行交易例子)
隔离性Isolation:
一个事务所做的修改在最终提交之前,对其他事务不可见。
持久性durability:
一旦事务提交,其所做的修改就会永久保存到数据库中。
2.MySql事务隔离级别
2.1未提交读Read uncommitted(脏读)
在B事务提交之前,A事务可以看到B事务带来的变化。(不锁定读)
2.2提交读Read committed(不可重复读)
一个事务范围内,在多次相同查询中可能看到不同的数据结果。(中间有B事务对其中数据进行了update等)
2.3可重复读Repeatable read
在同一个事务中多次读取同样记录的结果是一致的。(底层用MVCC多版本并发控制实现)(快照读)
2.4串行化Serializable
在读取的每一行数据上都加锁。(锁定读)
InnoDB进行Serializable时,每个select都会进行lock in share mode,不再支持非锁定读。
tips:幻读:A事务2次读过程中,B事务在A的查询范围里插入了一条新数据,于是A就看到了幻行。
3.MVCC多版本并发控制
InnoDB下的MVCC:
3.1实现方式
通过在每行记录后面保存在两个隐藏的列来实现:保存行的创建时间
保存行的过期时间(或删除时间)
注:存的不是实际的时间值,而是系统版本号
3.2运行过程
SELECT:只查找版本早于当前事务版本的数据行;行的删除版本要么未定义,要么大于当前事务版本号
INSERT:保存当前系统版本号作为行版本号
DELETE:为删除的每一行保存当前系统版本号作为行删除标识
UPDATE:也就是INSERT+DELETE
3.3MVCC解决了幻读?
MVCC解决了读数据情况下的幻读,没有解决修改的操作下的幻读问题。
3.4InnoDB解决幻读的方式
利用间隙锁。间隙锁是一个在索引记录之间的间隙上的锁。
4.事务的分类
InnoDB不原生支持嵌套事务,其他都支持。
4.1扁平事务Flat Transactions
事务中最简单的一种,从开始到结束,其间的操作是原子的。
4.2带有保存点的扁平事务Flat Transactions with Savepoint
在扁平事务基础上,允许回滚到同一事务中较早的一个状态。
保存点是易失的。
4.3链事务Chained Transaction
提交事务操作和开始下一个事务操作将合并为一个原子操作。
4.4嵌套事务Nested Transaction
层次结构。由一个顶层事务(top-level transaction)控制各个层次的事务。
处在叶节点的事务是扁平事务。
任何子事务都在顶层事务提交后才提交。
树中任何一个事务的回滚会引起它的所有子事务回滚。
在嵌套事务中,不同的子事务在数据库对象上持有的锁是不同的。这意味着比带有保存点的扁平事务更好的并发性。
4.5分布式事务
在分布式环境下运行的扁平事务,相当于多个数据节点的事务合并在一起并满足ACID特性。
5.重做日志redo log
redo log是物理日志,是幂等的(幂等:执行一次的效果和执行若干次的效果等同)。它记录页的物理修改,并在事务进行过程中不断写入。
默认情况下,事务提交时,把重做日志缓冲写入重做日志文件,并调用fsync,彻底持久化;
次之,可以通过修改参数不进行fsync,只写入文件系统缓存(数据库宕机没事,操作系统宕机会丢失);
再次之,可以通过修改参数在事务提交时不强制进行写入重做日志文件操作,仅由master thread每秒进行重做日志文件的fsync操作。
重做日志的写入可以保证原子性,不需要doublewrite技术(因为重做日志块的大小和磁盘扇区一样都是512字节)
6.undo
undo存放在数据库内部的一个特殊段(segment)中,称为undo segment。undo段位于共享表空间中。
除了回滚操作,undo的另一个作用是MVCC。即在InnoDB存储引擎中MVCC的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
undo log会产生redo log,这是因为undo log也需要持久性的保护。(事务在undo log segment分配页并写入undo log的这个过程,需要写入redo log)
undo log分为两种:
6.1insert undo log
insert undo log指的是在insert操作中产生的undo log。因为insert操作的记录只对事务本身可见,对其他事务不可见,所以这个undo log可以在事务提交后直接删除,不需要进行purge操作。
6.2update undo log
update undo log指的是在delete和update操作中产生的undo log。它需要用以实现MVCC,所以不能在事务提交时就删除。提交时放入undo log链表,等待purge线程进行最后的删除。
7.group commit
每次事务提交时都进行fsync太消耗性能。可以采用group commit来进行“组提交”,一次fsync刷新多个事务的重做日志。
8.MySQL分布式事务
InnoDB提供了对XA事务的支持,通过XA事务来支持分布式事务的实现。
在使用分布式事务时,InnoDB的事务隔离级别必须设置为SERIALIZABLE。
8.1XA事务
XA事务由一个或多个资源管理器(Resource Managers)、一个事务管理器(Transaction Manager)以及一个应用程序(Application Manager)组成。资源管理器提供访问事务资源的方法。通常一个数据库就是一个资源管理器
事务管理器协调参与全局事务中的各个事务。需要和参与全局事务的所有资源管理器进行通信。
应用程序定义事务的边界,指定全局事务中的操作。
在MySQL数据库的分布式事务中,资源管理器就是MySQL数据库,事务管理器为连接MySQL服务器的客户端。
8.2两段式提交two-phase commit
分布式事务使用两段式提交的方式。
第一阶段:所有参与全局事务的节点都开始准备,告诉事务管理器它们准备好提交了。
第二阶段:事务管理器告诉资源管理器执行ROLLBACK还是COMMIT。如果任何一个节点显示不能提交,那么所有的节点都会被告知回滚。