一、MySQL事务提交过程(一)

MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中。今天我们来讨论下事务的提交过程。

由于mysql插件式存储架构,导致开启binlog后,事务提交实质是二阶段提交,通过两阶段提交,来保证存储引擎和二进制日志的一致。

此目录节点只讨论binlog未打卡状态下的提交流程,后续会讨论打开binlog选项后的提交逻辑。

测试环境

OS:WIN7

ENGINE:

bin-log:off

DB:

测试条件

set autocommit=0;

------------------------------

--Table structure for `user`

------------------------------

DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (

`id`int(20) NOT NULL,

`account`varchar(20) NOT NULL,

`name`varchar(20) NOT NULL,PRIMARY KEY(`id`),KEY`id` (`id`) USING BTREE,KEY`name` (`name`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

测试语句

insert into user values(1, 'sanzhang', '张三');

commit;

一般常用的DML:Data Manipulation Language 数据操纵语言,对表的数据进行操作,(insert、update、delete )语句

和 DCL:Data Control Language 数据库控制语言(创建用户、删除用户、授权、取消授权)语句

和 DDL:Data Definition Language 数据库定义语言,对数据库内部的对象进行创建、删除、修改的操语句,

均是使用MySQL提供的公共接口mysql_execute_command,来执行相应的SQL语句。我们来分析下mysql_execute_command接口执行的流程:

mysql_execute_command

{

switch (command)

{caseSQLCOM_INSERT:

mysql_insert();break;caseSQLCOM_UPDATE:

mysql_update();break;caseSQLCOM_DELETE:

mysql_delete();break;

......

}if thd->is_error() //语句执行错误

trans_rollback_stmt(thd);elsetrans_commit_stmt(thd);

}

从上述流程中,可以看到执行任何语句,最后都会执行trans_rollback_stmt或者trans_commit_stmt,这两个分别是语句回滚和语句提交。

语句提交,对于非自动模式下,主要有两个作用:

1、释放autoinc锁,这个锁主要用来处理多个事务互斥的获取自增序列。因此,无论最后执行的是语句提交还是语句回滚,该资源都是需要立马释放掉的。

2、标识语句在事务中的位置,方便语句级回滚。执行commit后,可以进入commit流程。

现在看下具体的事务提交流程:

mysql_execute_command

trans_commit_stmt

ha_commit_trans(thd, FALSE);

{

TC_LOG_DUMMY:ha_commit_low

ha_commit_low()

innobase_commit

{//获取innodb层对应的事务结构

trx=check_trx_exists(thd);if(单个语句,且非自动提交)

{//释放自增列占用的autoinc锁资源

lock_unlock_table_autoinc(trx);//标识sql语句在事务中的位置,方便语句级回滚

trx_mark_sql_stat_end(trx);

}else事务提交

{

innobase_commit_low()

{

trx_commit_for_mysql();trx_commit(trx);

}//确定事务对应的redo日志是否落盘【根据flush_log_at_trx_commit参数,确定redo日志落盘方式】

trx_commit_complete_for_mysql(trx);

trx_flush_log_if_needed_low(trx->commit_lsn);

log_write_up_to(lsn);

}

}

}

trx_commit

trx_commit_low

{

trx_write_serialisation_history

{

trx_undo_update_cleanup//供purge线程处理,清理回滚页

}

trx_commit_in_memory

{

lock_trx_release_locks//释放锁资源

trx_flush_log_if_needed(lsn)//刷日志

trx_roll_savepoints_free//释放savepoints

}

}

MySQL是通过WAL方式,来保证数据库事务的一致性和持久性,即ACID特性中的C(consistent)和D(durability)。

WAL(Write-Ahead Logging)是一种实现事务日志的标准方法,具体而言就是:

1、修改记录前,一定要先写日志;

2、事务提交过程中,一定要保证日志先落盘,才能算事务提交完成。

通过WAL方式,在保证事务特性的情况下,可以提高数据库的性能。

从上述流程可以看出,提交过程中,主要做了4件事情,

1、清理undo段信息,对于innodb存储引擎的更新操作来说,undo段需要purge,这里的purge主要职能是,真正删除物理记录。在执行delete或update操作时,实际旧记录没有真正删除,只是在记录上打了一个标记,而是在事务提交后,purge线程真正删除,释放物理页空间。因此,提交过程中会将undo信息加入purge列表,供purge线程处理。

2、释放锁资源,mysql通过锁互斥机制保证不同事务不同时操作一条记录,事务执行后才会真正释放所有锁资源,并唤醒等待其锁资源的其他事务;

3、刷redo日志,前面我们说到,mysql实现事务一致性和持久性的机制。通过redo日志落盘操作,保证了即使修改的数据页没有即使更新到磁盘,只要日志是完成了,就能保证数据库的完整性和一致性;

4、清理保存点列表,每个语句实际都会有一个savepoint(保存点),保存点作用是为了可以回滚到事务的任何一个语句执行前的状态,由于事务都已经提交了,所以保存点列表可以被清理了。

关于mysql的锁机制,purge原理,redo日志,undo段等内容,其实都是数据库的核心内容。

MySQL 本身不提供事务支持,而是开放了存储引擎接口,由具体的存储引擎来实现,具体来说支持 MySQL 事务的存储引擎就是 InnoDB。

存储引擎实现事务的通用方式是基于 redo log 和 undo log。

简单来说,redo log 记录事务修改后的数据, undo log 记录事务前的原始数据。

所以当一个事务执行时实际发生过程简化描述如下:

先记录 undo/redo log,确保日志刷到磁盘上持久存储。

更新数据记录,缓存操作并异步刷盘。

提交事务,在 redo log 中写入 commit 记录。

在 MySQL 执行事务过程中如果因故障中断,可以通过 redo log 来重做事务或通过 undo log 来回滚,确保了数据的一致性。

这些都是由事务性存储引擎来完成的,但 binlog 不在事务存储引擎范围内,而是由 MySQL Server 来记录的。

那么就必须保证 binlog 数据和 redo log 之间的一致性,所以开启了 binlog 后实际的事务执行就多了一步,如下:

先记录 undo/redo log,确保日志刷到磁盘上持久存储。

更新数据记录,缓存操作并异步刷盘。

将事务日志持久化到 binlog。

提交事务,在 redo log 中写入commit记录。

这样的话,只要 binlog 没写成功,整个事务是需要回滚的,而 binlog 写成功后即使 MySQL Crash 了都可以恢复事务并完成提交。

要做到这点,就需要把 binlog 和事务关联起来,而只有保证了 binlog 和事务数据的一致性,才能保证主从数据的一致性。

所以 binlog 的写入过程不得不嵌入到纯粹的事务存储引擎执行过程中,并以内部分布式事务(xa 事务)的方式完成两阶段提交。

二、MySQL事务提交过程(二)

前一章节我们介绍了在关闭binlog的情况下,事务提交的大概流程。之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。

这里所谓的两阶段提交分别是prepare阶段和commit阶段。

内部xa事务主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog在mysql层,而redo log 在存储引擎层);

外部xa事务则是指支持多实例分布式事务,这个才算是真正的分布式事务。

既然是xa事务,必然涉及到两阶段提交,对于内部xa而言,同样存在着提交的两个阶段。

下文会结合源码详细解读内部xa的两阶段提交过程,以及各种情况下,mysqld crash后,mysql如何恢复来保证事务的一致性。

测试环境在前章节的基础上加了:

配置文件参数:

log-bin=D:\mysql\log\5-6-21\mysql-bin

binlog_format=ROWset autocommit=0;

innodb_support_xa=1sync_binlog=1;

innodb_flush_log_at_trx_commit=1;

【innodb_flush_log_at_trx_commit=1,sync_binlog=1

不同的模式区别在于,写文件调用write和落盘fsync调用的频率不同,所导致的后果是mysqld 或 os crash后,不严格的设置可能会丢失事务的更新。

双一模式是最严格的模式,这种设置情况下,单机在任何情况下不会丢失事务更新。】

prepare阶段:

1.设置undo state=TRX_UNDO_PREPARED; //trx_undo_set_state_at_prepare调用

2.刷事务更新产生的redo日志;【步骤1产生的redo日志也会刷入】

MYSQL_BIN_LOG::prepareha_prepare_low

{

engine:

binlog_prepare

innobase_xa_prepare

mysql:

trx_prepare_for_mysql

{1.trx_undo_set_state_at_prepare //设置undo段的标记为TRX_UNDO_PREPARED2.设置事务状态为TRX_STATE_PREPARED3.trx_flush_log_if_needed //将产生的redolog刷入磁盘

}

}

commit阶段:

1.将事务产生的binlog写入文件,刷入磁盘;

2.设置undo页的状态,置为TRX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;  // trx_undo_set_state_at_finish调用

3.记录事务对应的binlog偏移,写入系统表空间; //trx_sys_update_mysql_binlog_offset调用

MYSQL_BIN_LOG::commitordered_commit

{1.FLUSH_STAGE

flush_cache_to_file//刷binlog2.SYNC_STAGE

sync_binlog_file//Call fsync() to sync the file to disk.3.COMMIT_STAGE

ha_commit_low

{

binlog_commit

innobase_commit

trx_commit(trx)

{

trx_write_serialisation_history(trx, mtr);//更新binlog位点,设置undo状态

trx_commit_in_memory(trx, lsn);//释放锁资源,清理保存点列表,清理回滚段

}

}

}

在任何情况下(机器掉电)mysqld crash或者os crash,MySQL仍然能保证数据库的一致性。数据的一致性是如何做到的哪?正是二阶段提交。

我们结合几种场景来分析下二阶段提交是如何做到的:

1.prepare阶段,redo log落盘前,mysqld crash

2.prepare阶段,redo log落盘后,binlog落盘前,mysqld crash

3.commit阶段,binlog落盘后,mysqld crash

对于第一种情况,由于redo没有落盘,毫无疑问,事务的更新肯定没有写入磁盘,数据库的一致性受影响;

对于第二种情况,这时候redo log写入完成,但binlog还未写入,事务处于TRX_STATE_PREPARED状态,这是提交还是回滚呢?

对于第三种情况,此时,redo log和binlog都已经落盘,只是undo状态没有更新,虽然redo log和binlog已经一致了,事务是否应该提交?

我们结合mysqld异常重启后的执行逻辑以及关键的源代码。

对于第三种情况,我们可以搜集到未提交事务的binlog event,所以需要提交;

对于第二种情况,由于binlog未写入,需要通过执行回滚操作来保证数据库的一致性。

异常重启后,如何判断事务该提交还是回滚

1.读binlog日志,获取崩溃时没有提交的event;  //info->commit_list中含有该元素

2.若存在,则对应的事务要提交;否则需要回滚。

判断事务提交或回滚源码如下:

上面讨论了两阶段提交的基本流程,以及服务器异常crash后,mysql如何重启恢复保证binlog和数据的一致性。

简而言之,对于异常的xa事务,若binlog已落盘,则事务应该提交;binlog未落盘,则事务就应该回滚。

//异常重启后,回滚流程

innobase_rollback_by_xid

rollback_by_xid

trx_rollback_resurrected

trx_rollback_active

row_undo

{//从回滚页获取undo记录//分析undo记录类型if (insert)

row_undo_inselserow_undo_mod

}

//异常重启后,提交流程

commit_by_xid

trx_commit_for_mysql

//写binlog接口

handler.cc:binlog_log_row

sql/binlog.cc:commitmysys/my_sync:my_sync

sql/binlog.cc:sync_binlog_file

handler/ha_innodb.cc:innobase_xa_prepare

binlog日志文件是为了解决MySQL主从复制功能而引入的一份新日志文件,它包含了引发数据变更的事件日志集合。

从库请求主库发送 binlog 并通过日志事件还原数据写入从库,所以从库的数据来源为 binlog。

这样 MySQL 主库只需做到 binlog 与本地数据一致就可以保证主从库数据一致(暂且忽略网络传输引发的主从不一致)。

本文整理自:

https://www.cnblogs.com/exceptioneye/p/5451960.html

https://www.cnblogs.com/exceptioneye/p/5451976.html

mysql 提交事务_MySQL事务提交过程相关推荐

  1. mysql 提交_MySQL 事务提交过程

    开发老大要求通过binlog查询一条被修改的数据,数据被查出后问我,有没有可能binlog中不会记录,回答不会,因为数据被修改,若失败直接回滚,不会在binlog中记录,此刻一个朋友用了洪荒之力告诉我 ...

  2. linux mysql提交_MySQL 事务提交过程

    开发老大要求通过binlog查询一条被修改的数据,数据被查出后问我,有没有可能binlog中不会记录,回答不会,因为数据被修改,若失败直接回滚,不会在binlog中记录,此刻一个朋友用了洪荒之力告诉我 ...

  3. 列表数据提交_MySQL事务提交过程(一)

    MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提交过程. MySQL体系结构 由于mysql插件式存储架构,导致开启binlog后,事务提交实质是二阶段提交 ...

  4. mysql提交事务_mysql事务的实现原理

    此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中有一个整体的认识,如下图 如上图所示,My ...

  5. 4.事务提交过程,事务基本概念,Oracle中的事务生命周期,保存点savepoint,数据库的隔离级别

     事务提交过程 事务 基本概念 概念:一个或者多个DML语言组成 特点:要么都成功,要么都失败 事务的隔离性:多个客户端同时操作数据库的时候,要隔离它们的操作, 否则出现:脏读  不可重复读  幻 ...

  6. mysql事务在提交后才发送给数据库执行_从一个线上问题分析binlog与内部XA事务提交过程...

    1. 问题 业务上新增一条订单记录,用户接收到BinLake拉取的MySQL从库数据消息后,马上根据消息内的订单号去查询同一个MySQL从库,发现有些时候无法查到该条数据,等待大约500ms-1000 ...

  7. mysql事务回滚是什么意思_Mysql事务提交及事务回滚是什么意思

    本篇文章主要给大家介绍mysql事务提交及事务回滚的相关知识. 事务可以说是一段sql 语句的批处理,但是这个批处理是一个atom(原子) ,不可分割,要么都提交执行,要么回滚(rollback)都不 ...

  8. mysql事务所_MySQL事务,这篇文章就够了

    0 什么是事务 事务(Transaction) 是并发控制的基本单位.所谓的事务,它是一个操作序列,这些操作要么都 执行,要么都不执行,它是一个不可分割的工作单位.事务是数据库维护数据一致性的单位,在 ...

  9. mysql级别_mysql事务级别

    一.隔离级别 隔离级别(Isolation Level) SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并 ...

最新文章

  1. css超出一行添加省略号属性
  2. node封装mysql模块
  3. html5小说翻页,用html5模拟书的翻页
  4. 【机器学习算法专题(蓄力计划)】十、机器学习中必备的高等数学和线性代数基础
  5. django model filter_django中探索如何提高查询数据效率
  6. Win10上rabbitmq 安装
  7. Python 标准库 —— uuid(生成唯一 ID)
  8. activemq java 异步_异步消息处理机制之activeMQ应用实例
  9. java context.write_Channel.write() 和 ChannelHandlerContext.write() 的区别
  10. c语言中字符名词解释,C语言名词解释哪里有名词的解释 比如 什么型 什么型的...
  11. 【OSATE学习笔记】EMV2.aadl详解
  12. 苗条的生成树_苗条手册
  13. 大数据实验室第一次考核
  14. 亚马逊、微软、谷歌,谁将是5000亿美元云市场的C位?
  15. 公众号图文消息加html,微信公众号图文排版,如何给文章或者段落添加背景图?...
  16. 第五届蓝桥杯真题解析【JavaC组】
  17. PCSX2:PlayStation 2 游戏模拟器
  18. 二叉树线索化仍不能解决的两个问题及原因
  19. kali linux 2022更改国内软件源 WSL适用
  20. IBM公司的企业管理

热门文章

  1. java跨境电商ERP系统源码 亚马逊跨境电商全套源码SaaS系统
  2. Web开发技术的演变
  3. 『AidLux工业检测PaaS平台』轻松解决AI工业质检换产难问题!
  4. flink与spark的区别----阅读笔记1
  5. 推荐张艺谋年轻时的两部片子 :红高粱、千里走单骑
  6. 兄弟俩今年的年龄和是35岁,当哥哥像弟弟现在这样大时,弟弟的年龄恰好是哥哥年龄的一半,哥哥今年几岁?
  7. 中文文件名一键批量转换成英文名称
  8. RealMax携手乐视举办全球AR开发者大赛
  9. windows代理软件对比
  10. ADCLK905调试