学做网站开发吗,济南商城网站建设,长沙微信群,服务器创建多个网站吗分布式事务 1.分布式事务是什么#xff1f;数据库事务 2.分布式事务产生的原因#xff1f;存储层拆分服务层拆分 3.分布式事务解决方案4.分布式事务有哪些开源组件SeateTCC 分布式服务组件基于消息补偿的最终一致性 5.两阶段提交#xff0c;三阶段协议详解二阶段提交协议三阶… 分布式事务 1.分布式事务是什么数据库事务 2.分布式事务产生的原因存储层拆分服务层拆分 3.分布式事务解决方案4.分布式事务有哪些开源组件SeateTCC 分布式服务组件基于消息补偿的最终一致性 5.两阶段提交三阶段协议详解二阶段提交协议三阶段提交协议三阶段提交的改进两阶段和三阶段提交的应用 6.TCC 事务模型详解TCC 事务模型是什么TCC 的各个阶段TCC 的优缺点真实业务场景 TCC 7.MySQL 数据库如何实现 XA 内部分布式事务规范MySQL 有哪些一致性日志XA 规范是如何定义的XA 事务的执行流程MySQL 如何实现 XA 规范Binlog 同步过程 1.分布式事务是什么
分布式事务关注的是分布式场景下如何处理事务是指事务的参与者、支持事务操作的服务器、存储等资源分别位于分布式系统的不同节点之上。
分布式事务就是一个业务操作是由多个细分操作完成的而这些细分操作又分布在不同的服务器上
事务就是这些操作要么全部成功执行要么全部不执行。
数据库事务
数据库事务的特性包括原子性Atomicity、一致性Consistency、隔离性Isolation和持久性Durabilily简称 ACID。
在数据库执行中多个并发执行的事务如果涉及到同一份数据的读写就容易出现数据不一致的情况不一致的异常现象有以下几种。 脏读是指一个事务中访问到了另外一个事务未提交的数据。例如事务 T1 中修改的数据项在尚未提交的情况下被其他事务T2读取到如果 T1 进行回滚操作则 T2 刚刚读取到的数据实际并不存在。 **不可重复读是指一个事务读取同一条记录 2 次得到的结果不一致。**例如事务 T1 第一次读取数据接下来 T2 对其中的数据进行了更新或者删除并且 Commit 成功。这时候 T1 再次读取这些数据那么会得到 T2 修改后的数据发现数据已经变更这样 T1 在一个事务中的两次读取返回的结果集会不一致。 幻读是指一个事务读取 2 次得到的记录条数不一致。例如事务 T1 查询获得一个结果集T2 插入新的数据T2 Commit 成功后T1 再次执行同样的查询此时得到的结果集记录数不同。 脏读、不可重复读和幻读有以下的包含关系如果发生了脏读那么幻读和不可重复读都有可能出现。 不同隔离级别
SQL 标准根据三种不一致的异常现象将隔离性定义为四个隔离级别Isolation Level隔离级别和数据库的性能呈反比隔离级别越低数据库性能越高而隔离级别越高数据库性能越差具体如下
1Read uncommitted 读未提交
在该级别下一个事务对数据修改的过程中不允许另一个事务对该行数据进行修改但允许另一个事务对该行数据进行读不会出现更新丢失但会出现脏读、不可重复读的情况。
2Read committed 读已提交
在该级别下未提交的写事务不允许其他事务访问该行不会出现脏读但是读取数据的事务允许其他事务访问该行数据因此会出现不可重复读的情况。
3Repeatable read 可重复读
在该级别下在同一个事务内的查询都是和事务开始时刻一致的保证对同一字段的多次读取结果都相同除非数据是被本身事务自己所修改不会出现同一事务读到两次不同数据的情况。因为没有约束其他事务的新增Insert操作所以 SQL 标准中可重复读级别会出现幻读。
可重复读是 MySQL InnoDB 引擎的默认隔离级别但是在 MySQL 额外添加了间隙锁Gap Lock可以防止幻读。
4Serializable 序列化
该级别要求所有事务都必须串行执行可以避免各种并发引起的问题效率也最低。
对不同隔离级别的解释其实是为了保持数据库事务中的隔离性Isolation目标是使并发事务的执行效果与串行一致隔离级别的提升带来的是并发能力的下降两者是负相关的关系。
2.分布式事务产生的原因
分布式事务是伴随着系统拆分出现的前面我们说过分布式系统解决了海量数据服务对扩展性的要求但是增加了架构上的复杂性在这一点上分布式事务就是典型的体现。
**在实际开发中**分布式事务产生的原因主要来源于存储和服务的拆分。
存储层拆分
存储层拆分最典型的就是数据库分库分表当单表容量达到千万级就要考虑数据库拆分从单一数据库变成多个分库和多个分表。在业务中如果需要进行跨库或者跨表更新同时要保证数据的一致性就产生了分布式事务问题。 服务层拆分
服务层拆分也就是业务的服务化系统架构的演进是从集中式到分布式业务功能之间越来越解耦合。
比如电商网站系统业务初期可能是一个单体工程支撑整套服务但随着系统规模进一步变大大多数公司都会将核心业务抽取出来以作为独立的服务。商品、订单、库存、账号信息都提供了各自领域的服务业务逻辑的执行散落在不同的服务器上。
用户如果在某网站上进行一个下单操作那么会同时依赖订单服务、库存服务、支付扣款服务这几个操作如果有一个失败那下单操作也就完不成这就需要分布式事务来保证了。 3.分布式事务解决方案
分布式事务的解决方案典型的有两阶段和三阶段提交协议、 TCC 分段提交和基于消息队列的最终一致性设计。
2PC 两阶段提交
两阶段提交2PCTwo-phase Commit Protocol是非常经典的强一致性、中心化的原子提交协议在各种事务和一致性的解决方案中都能看到两阶段提交的应用。
3PC 三阶段提交
三阶段提交协议3PCThree-phase_commit_protocol是在 2PC 之上扩展的提交协议主要是为了解决两阶段提交协议的阻塞问题从原来的两个阶段扩展为三个阶段增加了超时机制。
TCC 分段提交
TCC 是一个分布式事务的处理模型将事务过程拆分为 Try尝试、Confirm确定、Cancel 取消三个步骤在保证强一致性的同时最大限度提高系统的可伸缩性与可用性。
基于消息补偿的最终一致性√
异步化在分布式系统设计中随处可见基于消息队列的最终一致性就是一种异步事务机制在业务中广泛应用。
4.分布式事务有哪些开源组件
Seate
分布式事务开源组件应用比较广泛的是蚂蚁金服开源的 Seata也就是 Fescar前身是阿里中间件团队发布的 TXCTaobao Transaction Constructor和升级后的 GTSGlobal Transaction Service。
Seata 的设计思想是把一个分布式事务拆分成一个包含了若干分支事务Branch Transaction的全局事务Global Transaction。分支事务本身就是一个满足 ACID 的 本地事务全局事务的职责是协调其下管辖的分支事务达成一致要么一起成功提交要么一起失败回滚。 在Seata 中全局事务对分支事务的协调基于两阶段提交协议类似数据库中的 XA 规范XA 规范定义了三个组件来协调分布式事务分别是 AP 应用程序、TM 事务管理器、RM 资源管理器、CRM 通信资源管理器。
TCC 分布式服务组件
在业务中引入 TCC 一般是依赖单独的 TCC 事务框架可以选择自研或者应用开源组件。TCC 框架扮演了资源管理器的角色常用的 TCC 开源组件有 Tcc-transaction、ByteTCC、Spring-cloud-rest-tcc 等。
TCC 事务模式也支持了 AT 模式及 Saga 模式。
以 Tcc-transaction https://github.com/changmingxie/tcc-transaction为例源码托管在 Github-tcc-transaction提供了对 Spring 和 Dubbo 的适配 tcc-transaction-tutorial-samplehttps://github.com/changmingxie/tcc-transaction/tree/master-1.2.x/tcc-transaction-tutorial-sample 学习。
基于消息补偿的最终一致性
在具体实现上基于消息补偿的一致性主要有本地消息表和第三方可靠消息队列等。
本地消息表本地消息表的方案核心思想是将分布式事务拆分成本地事务进行处理通过消息日志的方式来异步执行。
本地消息表是一种业务耦合的设计消息生产方需要额外建一个事务消息表并记录消息发送状态消息消费方需要处理这个消息并完成自己的业务逻辑另外会有一个异步机制来定期扫描未完成的消息确保最终一致性。
下单减库存业务来简单模拟本地消息表的实现过程
1系统收到下单请求将订单业务数据存入到订单库中并且同时存储该订单对应的消息数据比如购买商品的 ID 和数量消息数据与订单库为同一库更新订单和存储消息为一个本地事务要么都成功要么都失败。
2库存服务通过消息中间件收到库存更新消息调用库存服务进行业务操作同时返回业务处理结果。
3消息生产方也就是订单服务收到处理结果后将本地消息表的数据删除或者设置为已完成。
4设置异步任务定时去扫描本地消息表发现有未完成的任务则重试保证最终一致性。
在具体实践中还有许多分支情况比如消息发送失败、下游业务方处理失败等
5.两阶段提交三阶段协议详解
二阶段提交协议
二阶段提交算法的成立
在该分布式系统中存在一个节点作为 协调者Coordinator其他节点作为 参与者Participants且节点之间可以进行网络通信
所有节点都采用预写式日志日志被写入后被保存在可靠的存储设备上即使节点损坏也不会导致日志数据的丢失
所有节点不会永久性损坏即使损坏后仍然可以恢复。
两阶段提交中的两个阶段指的是 Commit-request 阶段和 Commit 阶段两阶段提交的流程如下 提交请求阶段
在提交请求阶段协调者将通知 事务参与者准备提交事务然后进入表决过程。在表决过程中参与者将告知协调者自己的决策同意事务参与者本地事务执行成功或取消本地事务执行故障在第一阶段参与节点并没有进行Commit操作。
提交阶段
在提交阶段协调者将基于第一个阶段的投票结果进行决策提交或取消这个事务。这个结果的处理必须当且仅当所有的参与者同意提交协调者才会通知各个参与者提交事务否则协调者将通知各个参与者取消事务。
参与者在接收到协调者发来的消息后将执行对应的操作也就是本地 Commit 或者 Rollback。
两阶段提交存在的问题 两阶段提交协议有几个明显的问题:
资源被同步阻塞
在执行过程中所有参与节点都是事务独占状态当参与者占有公共资源时那么第三方节点访问公共资源会被阻塞。
协调者可能出现单点故障
一旦协调者发生故障参与者会一直阻塞下去。
在 Commit 阶段出现数据不一致
在第二阶段中假设协调者发出了事务 Commit 的通知但是由于网络问题该通知仅被一部分参与者所收到并执行 Commit其余的参与者没有收到通知一直处于阻塞状态那么这段时间就产生了数据的不一致性。
三阶段提交协议
为了解决二阶段协议中的同步阻塞等问题三阶段提交协议在协调者和参与者中都引入了【超时机制】并且把两阶段提交协议的第一个阶段拆分成了两步询问然后再锁资源最后真正提交。
三阶段中的 Three Phase 分别为 CanCommit、PreCommit、DoCommit 阶段。 CanCommit 阶段准备阶段
3PC 的 CanCommit 阶段其实和 2PC 的准备阶段很像。协调者向参与者发送 Can-Commit 请求参与者如果可以提交就返回 Yes 响应否则返回 No 响应。
PreCommit 阶段预提交阶段
协调者根据参与者的反应情况来决定是否可以继续事务的 PreCommit 操作。根据响应情况有以下两种可能。
A. 假如协调者从所有的参与者获得的反馈都是 Yes 响应那么就会进行事务的预执行 发送预提交请求协调者向参与者发送 PreCommit 请求并进入 Prepared 阶段 事务预提交参与者接收到 PreCommit 请求后会执行事务操作 响应反馈如果参与者成功执行了事务操作则返回 ACK 响应同时开始等待最终指令。
B. 假如有任何一个参与者向协调者发送了 No 响应或者等待超时之后协调者都没有接到参与者的响应那么就中断事务 发送中断请求协调者向所有参与者发送 abort 请求 中断事务参与者收到来自协调者的 abort 请求之后执行事务的中断。
DoCommit 阶段提交阶段
该阶段进行真正的事务提交也可以分为以下两种情况。
A. 执行提交
发送提交请求。协调者接收到参与者发送的 ACK 响应后那么它将从预提交状态进入到提交状态并向所有参与者发送 doCommit 请求。事务提交。参与者接收到 doCommit 请求之后执行正式的事务提交并在完成事务提交之后释放所有事务资源。响应反馈。事务提交完之后向协调者发送 ACK 响应。完成事务。协调者接收到所有参与者的 ACK 响应之后完成事务。
B. 中断事务
协调者没有接收到参与者发送的 ACK 响应可能是因为接受者发送的不是 ACK 响应也有可能响应超时了那么就会执行中断事务。
C.超时提交
参与者如果没有收到协调者的通知超时之后会执行 Commit 操作。
三阶段提交的改进
1.引入超时机制
在 2PC 中只有协调者拥有超时机制如果在一定时间内没有收到参与者的消息则默认失败3PC 同时在协调者和参与者中都引入超时机制。
2.添加预提交阶段
在 2PC 的准备阶段和提交阶段之间插入一个准备阶段使 3PC 拥有 CanCommit、PreCommit、DoCommit 三个阶段PreCommit 是一个缓冲保证了在最后提交阶段之前各参与节点的状态是一致的。
3.三阶段提交协议存在的问题
三阶段提交协议同样存在问题具体表现为在阶段三中如果参与者接收到了 PreCommit 消息后出现了不能与协调者正常通信的问题在这种情况下参与者依然会进行事务的提交这就出现了数据的不一致性。
两阶段和三阶段提交的应用 两阶段提交是一种比较精简的一致性算法/协议很多关系型数据库都是采用两阶段提交协议来完成分布式事务处理的典型的比如 MySQL 的 XA 规范。 在事务处理、数据库和计算机网络中两阶段提交协议提供了分布式设计中的数据一致性的保障整个事务的参与者要么一致性全部提交成功要么全部回滚。MySQL Cluster 内部数据的同步就是用的 2PC 协议。
6.TCC 事务模型详解
TCC 事务模型是什么
TCCTry-Confirm-Cancel的概念来源于 Pat Helland 发表的一篇名为“Life beyond Distributed Transactions:an Apostate’s Opinion”的论文。
TCC 提出了一种新的事务模型基于业务层面的事务定义锁粒度完全由业务自己控制目的是解决复杂业务中跨表跨库等大颗粒度资源锁定的问题。
TCC 把事务运行过程分成 Try、Confirm / Cancel 尝试、确认与取消两个阶段每个阶段的逻辑由业务代码控制避免了长事务可以获取更高的性能。
TCC 的各个阶段
流程图 Try 阶段调用 Try 接口尝试执行业务完成所有业务检查预留业务资源。 Confirm 或 Cancel 阶段两者是互斥的只能进入其中一个并且都满足幂等性允许失败重试。 Confirm 操作对业务系统做确认提交确认执行业务操作不做其他业务检查只使用 Try 阶段预留的业务资源。 Cancel 操作在业务执行错误需要回滚的状态下执行业务取消释放预留资源。
Try 阶段失败可以 Cancel如果 Confirm 和 Cancel 阶段失败了怎么办
TCC 中会添加事务日志如果 Confirm 或者 Cancel 阶段出错则会进行重试所以这两个阶段需要支持幂等。如果重试失败则需要人工介入进行恢复和处理等。
TCC 的优缺点
实际开发中TCC 的本质是把数据库的二阶段提交上升到微服务来实现从而避免数据库二阶段中长事务引起的低性能风险。
TCC 解决了跨服务的业务操作原子性问题比如下订单减库存多渠道组合支付等场景通过 TCC 对业务进行拆解可以让应用自己定义数据库操作的粒度可以降低锁冲突提高系统的业务吞吐量。
TCC 的不足主要体现在对微服务的侵入性强TCC 需要对业务系统进行改造业务逻辑的每个分支都需要实现 try、Confirm、Cancel 三个操作并且 Confirm、Cancel 必须保证幂等。
另外 TCC 的事务管理器要记录事务日志也会损耗一定的性能。
真实业务场景 TCC
以一个电商中的支付业务来演示用户在支付以后需要进行更新订单状态、扣减账户余额、增加账户积分和扣减商品操作。
在实际业务中为了防止超卖有下单减库存和付款减库存的区别支付除了账户余额还有各种第三方支付等这里我们为了描述方便统一使用扣款减库存扣款来源是用户账户余额。 我们把订单业务拆解为以下几个步骤
订单更新为支付完成状态扣减用户账户余额增加用户账户积分扣减当前商品的库存
如果不使用事务上面的几个步骤都可能出现失败最终会造成大量的数据不一致比如订单状态更新失败扣款却成功了或者扣款失败库存却扣减了等情况这个在业务上是不能接受的会出现大量的客诉。
如果直接应用事务不使用分布式事务比如在代码中添加 Spring 的声明式事务 Transactional 注解这样做实际上是在事务中嵌套了远程服务调用一旦服务调用出现超时事务无法提交就会导致数据库连接被占用出现大量的阻塞和失败会导致服务宕机。另一方面如果没有定义额外的回滚操作比如遇到异常非 DB 的服务调用失败时则无法正确执行回滚。
所以需要对业务代码改造抽象 Try、Confirm 和 Cancel 阶段。
Try 操作
Try 操作一般都是锁定某个资源设置一个预备的状态冻结部分数据。
比如订单服务添加一个预备状态修改为 UPDATING也就是更新中的意思冻结当前订单的操作而不是直接修改为支付成功。
库存服务设置冻结库存可以扩展字段也可以额外添加新的库存冻结表。
积分服务和库存一样添加一个预增加积分比如本次订单积分是 100添加一个额外的存储表示等待增加的积分账户余额服务等也是一样的操作。
Confirm 操作
Confirm 操作就是把前边的 Try 操作锁定的资源提交类比数据库事务中的 Commit 操作。在支付的场景中包括订单状态从准备中更新为支付成功库存数据扣减冻结库存积分数据增加预增加积分。
Cancel 操作
Cancel 操作执行的是业务上的回滚处理类比数据库事务中的 Rollback 操作。首先订单服务撤销预备状态还原为待支付状态或者已取消状态库存服务删除冻结库存添加到可销售库存中积分服务也是一样将预增加积分扣减掉。
执行业务操作
下面来分析业务的实际执行操作首先业务请求过来开始执行 Try 操作如果 TCC 分布式事务框架感知到各个服务的 Try 阶段都成功了以后就会执行各个服务的 Confirm 逻辑。
如果 Try 阶段有操作不能正确执行比如订单失效、库存不足等就会执行 Cancel 的逻辑取消事务提交。
7.MySQL 数据库如何实现 XA 内部分布式事务规范
MySQL 有哪些一致性日志
如果 MySQL 数据库断电了未提交的事务怎么办
依靠日志因为在执行一个操作之前数据库会首先把这个操作的内容写入到文件系统日志里记录起来然后再进行操作。当宕机或者断电的时候即使操作并没有执行完但是日志在操作前就已经写好了我们仍然可以根据日志的内容来进行恢复。
MySQL InnoDB 引擎中和一致性相关的有
重做日志redo log
回滚日志undo log
二进制日志binlog
**redo 日志**每当有操作执行前在数据真正更改前会先把相关操作写入 redo 日志。这样当断电或者发生一些意外导致后续任务无法完成时待系统恢复后可以继续完成这些更改。
和 redo 日志对应的 undo 日志也叫撤消日志记录事务开始前数据的状态当一些更改在执行一半时发生意外而无法完成就可以根据撤消日志恢复到更改之前的状态。
举个例子事务 T1 更新数据 X对 X 执行 Update 操作从 10 更新到 20对应的 Redo 日志为T1,X,20 UndoT1,X,10 日志为 。
binlog 日志是 MySQL sever 层维护的一种二进制日志是 MySQL 最重要的日志之一它记录了所有的 DDL 和 DML 语句除了数据查询语句 select、show 等还包含语句所执行的消耗时间。
binlog 与 InnoDB 引擎中的 redo/undo log 不同binlog 的主要目的是复制和恢复用来记录对 MySQL 数据更新或潜在发生更新的 SQL 语句并以事务日志的形式保存在磁盘中。
binlog 主要应用在 MySQL 的主从复制过程中MySQL 集群在 Master 端开启 binlogMaster 把它的二进制日志传递给 slaves 节点再从节点回放来达到 master-slave 数据一致的目的。
//查看binlog文件的内容
show binlog events;//查看指定binlog文件的内容
show binlog events in MySQL-bin.000001;//查看正在写入的binlog文件
show master status\G//获取binlog文件列表
show binary logs;XA 规范是如何定义的
XA 是由 X/Open 组织提出的分布式事务规范XA 规范主要定义了事务协调者Transaction Manager和 资源管理器Resource Manager之间的接口。 事务协调者Transaction Manager
因为 XA 事务是基于两阶段提交协议的所以需要有一个协调者来保证所有的事务参与者都完成了准备工作也就是 2PC 的第一阶段。如果事务协调者收到所有参与者都准备好的消息就会通知所有的事务都可以提交也就是 2PC 的第二阶段。
之所以需要引入事务协调者是因为在分布式系统中两台机器理论上无法达到一致的状态需要引入一个单点进行协调。协调者也就是事务管理器控制着全局事务管理事务生命周期并协调资源。
资源管理器Resource Manager
负责控制和管理实际资源比如数据库或 JMS 队列。
目前主流数据库都提供了对 XA 的支持在 JMS 规范中即 Java 消息服务Java Message Service中也基于 XA 定义了对事务的支持。
XA 事务的执行流程
XA 事务是两阶段提交的一种实现方式根据 2PC 的规范XA 将一次事务分割成了两个阶段即 Prepare 和 Commit 阶段。
Prepare 阶段
TM 向所有 RM 资源管理器发送 prepare 指令RM 接受到指令后执行数据修改和日志记录等操作然后返回可以提交或者不提交的消息给 TM。
如果事务协调者 TM收到所有参与者都准备好的消息会通知所有的事务提交然后进入第二阶段。
Commit 阶段
TM 接受到所有 RM 的 prepare 结果如果有 RM 返回是不可提交或者超时那么向所有 RM 发送 Rollback 命令
如果所有 RM 都返回可以提交那么向所有 RM 发送 Commit 命令完成一次事务操作。
MySQL 如何实现 XA 规范
MySQL 中 XA 事务有两种情况内部 XA 和外部 XA其区别是事务发生在 MySQL 服务器单机上还是发生在多个外部节点间上。
内部 XA
在 MySQL 的 InnoDB 存储引擎中开启 binlog 的情况下MySQL 会同时维护 binlog 日志与 InnoDB 的 redo log为了保证这两个日志的一致性MySQL 使用了 XA 事务由于是在 MySQL 单机上工作所以被称为内部 XA。
内部 XA 事务由 binlog 作为协调者在事务提交时则需要将提交信息写入二进制日志也就是说binlog 的参与者是 MySQL 本身。
外部 XA
外部 XA 就是典型的分布式事务MySQL 支持 XA START/END/PREPARE/Commit 这些 SQL 语句通过使用这些命令可以完成分布式事务。
MySQL 外部 XA 主要应用在数据库代理层实现对 MySQL 数据库的分布式事务支持例如开源的数据库中间层比如淘宝的 TDDL、阿里巴巴 B2B 的 Cobar 等。外部 XA 一般是针对跨多 MySQL 实例的分布式事务需要应用层作为协调者比如我们在写业务代码在代码中决定提交还是回滚并且在崩溃时进行恢复。
Binlog 中的 Xid
**当事务提交时在 binlog 依赖的内部 XA 中额外添加了 Xid 结构binlog 有多种数据类型包括以下三种
statement 格式记录为基本语句包含 Commitrow 格式记录为基于行mixed 格式日志记录使用混合格式
不论是 statement 还是 row 格式binlog 都会添加一个XID_EVENT 作为事务的结束该事件记录了事务的 ID 也就是 Xid在 MySQL 进行崩溃恢复时根据 binlog 中提交的情况来决定如何恢复。
Binlog 同步过程
Binlog 下的事务提交过程整体过程是先写 redo log再写 binlog并以 binlog 写成功为事务提交成功的标志。 当有事务提交时
第一步InnoDB 进入 Prepare 阶段并且 write/sync redo log写 redo log将事务的 XID 写入到 redo 日志中binlog 不作任何操作第二步进行 write/sync Binlog写 binlog 日志也会把 XID 写入到 Binlog第三步调用 InnoDB 引擎的 Commit 完成事务的提交将 Commit 信息写入到 redo 日志中。如果是在第一步和第二步失败则整个事务回滚如果是在第三步失败则 MySQL 在重启后会检查 XID 是否已经提交若没有提交也就是事务需要重新执行就会在存储引擎中再执行一次提交操作保障 redo log 和 binlog 数据的一致性防止数据丢失。
在实际执行中还牵扯到操作系统缓存 Buffer 何时同步到文件系统中所以 MySQL 支持用户自定义在 Commit 时如何将 log buffer 中的日志刷到 log file 中通过变量 innodb_flush_log_at_trx_Commit 的值来决定。