一、事务的实现
事务的隔离性通过锁来实现,原子性、一致性、持久性则通过redo log和undo log实现。redo log保证原子性和持久性,undo log保证一致性。
1.1 redo
重做日志用来实现事务的持久性,由两部分组成:
-
内存中的重做日志缓冲(redologbuffer),其是易失的;
-
重做日志文件(redologfile),其是持久的。
redo log与undo log
redo log用来保证事务的持久性,undo log用来帮助事务回滚及MVCC功能。
redo log基本都是顺序写,而undo log需要进行随机读写
重做缓冲区写入重做日志文件的过程
重做日志缓冲先写入文件系统缓冲,为确保重做日志写入磁盘,必须进行一次fsync操作。
磁盘的性能决定了事务提交的性能,也就是数据库的性能
重做日志刷新到磁盘的策略
通过参数innodb_flush_log_at_trx_commit来控制重做日志刷新到磁盘的策略
-
1:默认值,即表示事务提交时必须调用一次fsync。
-
0:表示事务提交时不进行写入重做日志操作,这个操作仅在master线程中完成
-
2:表示事务提交时将重做日志写入重做日志文件,但仅写入文件系统的缓冲中,不进行fsync操作。
binlog与redolog的区别
-
产生的位置不同:重做日志是InnoDB存储引擎层产生;二进制日志是mysql数据库的上层产生的。二进制日志针对MySQL数据库中的任何存储引擎对数据库的更改都会产生二进制日志
-
记录的内容形式不同:二进制日志是逻辑日志,记录的是对应的SQL语句。重做日志是物理格式日志,记录的是对每个页的修改。
-
写入磁盘时间点不同:二进制日志只在事务提交完成后进行一次写入。重做日志在事务进行中不断地被写入,并不是随事务提交的顺序进行写入的。
1.1.2 log block
重做日志缓冲、重做日志文件都是一512字节的块的方式进行保存的,称之为重做日志块(redo log block)。
若一个页中产生的重做日志数量大于512字节,则需要分割为多个重做日志块进行存储。
由于重做日志块的大小和磁盘扇区大小一致,均为512字节,因此重做日志的写入可以保证原子性,不需要两次写技术。
1.1.3 log group
log group为重做日志组,其中有多个重做日志文件。log group是逻辑上的概念,并没有实际存储的物理文件表示log group。
InnoDB存储引擎只有1个log group
每个log group可容纳512GB大小的重做文件。
1.2 undo
1.2.1 基本概念
在对数据库进行修改时,InnoDB存储引擎不但会产生redo,还会产生一定量的undo,若事务语句失败,或请求回滚,则利用undo信息回滚到修改之前的样子。
undo存放在数据库内部的一个特殊段中,成为undo段。undo段位于共享表空间内。
undo是逻辑日志,指示将数据库逻辑地恢复到原来的样子。
undo的另一个作用是MVCC,即在InnoDB存储引擎中MVCC的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
1.2.2 undo存储管理
InnoDB存储引擎有rollback segment,每个回滚段种记录了1024个undo log segment,而在每个undo log segment段中进行undo页的申请。
二、分布式事务
InnoDB存储引擎提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。
分布式事务指的是允许多个独立的事务资源(transactional resources)参与到一个全局的事务中。
全局事务要求在其中的所有参与的事务要么都提交,要么都回滚。
在使用分布式事务时,InnoDB存储引擎的事务隔离级别必须设置为SERIALIZABLE。
什么是XA事务
XA事务允许不同数据库之间的分布式事务(不一定非是MySQL数据库),只要参与在全局事务中的每个节点都支持XA事务。
XA事务由一个或多个资源管理器(Resource Managers)、一个事务管理器(Transaction Manager)以及一个应用程序(Application Program)组成。
-
资源管理器:提供访问事务资源的方法。通常一个数据库就是一个资源管理器。
-
事务管理器:协调参与全局事务中的各个事务。需要和参与全局事务的所有资源管理器进行通信。
-
应用程序:定义事务的边界,指定全局事务中的操作。
分布式事务的两段式提交
分布式事务使用两段式提交(two-phase commit)的方式。
-
第一阶段:所有参与全局事务的节点都开始准备(PREPARE),告诉事务管理器它们准备好提交了。
-
第二阶段:事务管理器告诉资源管理器执行ROLLBACK还是COMMIT。
如果任何一个节点显示不能提交,则所有的节点都被告知需要回滚。
与本地事务区别:分布式事务多一次的PREPARE操作,待收到所有节点的同意信息后,再进行COMMIT或是ROLLBACK操作。