linux mysql提交_MySQL 事务提交过程

开发老大要求通过binlog查询一条被修改的数据,数据被查出后问我,有没有可能binlog中不会记录,回答不会,因为数据被修改,若失败直接回滚,不会在binlog中记录,此刻一个朋友用了洪荒之力告诉我,失败的话也会记录,坐地无语,因为他sqlserver dba,用sqlserver的思维考虑MySQL,哈哈哈哈哈,用实验让他闭嘴!

简单测试步骤如下:

root(yoon)> flush logs;

Query OK, 0 rows affected (0.01 sec)

root((none))> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| Log_name        | Pos | Event_type  | Server_id | End_log_pos | Info                                  |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| mysql-bin.000041 |  4 | Format_desc |    232242 |        120 | Server ver: 5.6.26-log, Binlog ver: 4 |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

root(yoon)> begin;

Query OK, 0 rows affected (0.00 sec)

root(yoon)> update yoon set id=7 where id=1;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1  Changed: 1  Warnings: 0

在没有commit情况下,二进制日志的位置偏移量未发生变化:

root(yoon)> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| Log_name        | Pos | Event_type  | Server_id | End_log_pos | Info                                  |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| mysql-bin.000041 |  4 | Format_desc |    232242 |        120 | Server ver: 5.6.26-log, Binlog ver: 4 |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

root(yoon)> commit;

Query OK, 0 rows affected (1.01 sec)

提交后再次查看日志偏移量,发生变化,并记录在binlog中

root(yoon)> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

| Log_name        | Pos | Event_type  | Server_id | End_log_pos | Info                                        |

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

| mysql-bin.000041 |  4 | Format_desc |    232242 |        120 | Server ver: 5.6.16-log, Binlog ver: 4      |

| mysql-bin.000041 | 120 | Query      |    232242 |        199 | BEGIN                                      |

| mysql-bin.000041 | 199 | Query      |    232242 |        304 | use `yoon`; update yoon set id=7 where id=1 |

| mysql-bin.000041 | 304 | Xid        |    232242 |        335 | COMMIT /* xid=18 */                        |

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

MySQL事务提交过程

开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。

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

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

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

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

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

数据库版本:5.6.16

操作系统版本:CentOS 6.5

配置文件参数:

log-bin=/my/log/mysql-bin

binlog_format=ROW

set autocommit=0

innodb_support_xa=1

sync_binlog=1

innodb_flush_log_at_trx_commit=1

【innodb_flush_log_at_trx_commit=1,sync_binlog=1

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

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

测试条件:

set autocommit=0;

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;

prepare阶段:

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

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

MYSQL_BIN_LOG::prepare

ha_prepare_low

{

engine:

binlog_prepare

innobase_xa_prepare

mysql:

trx_prepare_for_mysql

{

1.trx_undo_set_state_at_prepare    //设置undo段的标记为TRX_UNDO_PREPARED

2.设置事务状态为TRX_STATE_PREPARED

3.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::commit

ordered_commit

{

1.FLUSH_STAGE

flush_cache_to_file  //  刷binlog

2.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.若存在,则对应的事务要提交;否则需要回滚。

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

1a4d5bd2677b9902098b357f39c96be2.png

上面讨论了两阶段提交的基本流程,以及服务器异常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_ins else row_undo_mod

}

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

commit_by_xid

trx_commit_for_mysql

//写binlog接口

handler.cc:binlog_log_row

sql/binlog.cc:commit

mysys/my_sync:my_sync

sql/binlog.cc:sync_binlog_file

handler/ha_innodb.cc:innobase_xa_prepare

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

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

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

0b1331709591d260c1c78e86d0c51c18.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393488.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React单元测试:Jest + Enzyme(二)

前言 在上一篇教程中,我们成功搭建了基于Jest和Enzyme的单元测试框架并成功地跑起来第一个单元测试,可以点击这里回顾一下。今天,我们重点讨论如何通过Jest来mock数据。 什么是Mock Mock的简单翻译就是模拟。既可以模拟数据,也可以…

python dict hash算法_2020年3月26日python学习笔记——hash

什么是哈希?hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远…

数据处理不等式:Data Processing Inequality

我是在差分隐私下看到的,新解决方案的可用性肯定小于原有解决方案的可用性,也就是说信息的后续处理只会降低所拥有的信息量。 那么如果这么说的话为什么还要做特征工程呢,这是因为该不等式有一个巨大的前提就是数据处理方法无比的强大&#x…

gulp 实现sass自动化 ,监听同步

实现功能 监听scss文件   sass自动化 准备条件 1 .安装gulp npm init ---->一直enter,会在当前目录下生成一个package.json文件,记录安装的依赖模块 npm install gulp --save-dev 2 .安装gulp-ruby-sass npm install gulp-ruby-sass 你还需要安装ruby环境…

MSSQL → 02:数据库结构

一、数据库的组成 在SQL Server 2008中,用户如何访问及使用数据库,就需要正确了解数据库中所有对象及其设置。数据库就像一个容器,它里面除了存放着数据的表之外,还有视图、存储过程、触发器、约束等数据库对象。数据库管理的核心…

mySQL教程 第9章 触发器

第9章 触发器 入的新数据放到new表,删除的数据放到old表。 准备本章学习环境 连接数据库schoolDB,删除表TStudent,TScore和Tsubject中的所有数据。 delete from TStudent; delete from TScore; delete from TSubject; 向学生表插入两条记录 i…

掩码图制作photoshop__新手用

1.首先你得有一张图,比如这样的: 2.用PS打开他 3.左边工具栏里(快速选择工具W),选想显示的部分 4.ctrlc复制一下,新建一张黑底图粘贴上去或者白底图时选中显示区即花瓣右键反向右键填充成黑色 5.菜单栏->…

Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现

大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和动画,并展示当前的手牌。这期我们继续实现接下来的功能--叫地主。 1.首先这两天,学习了DOTween,这是一个强大的Unity动画插件,大家可以参考&#…

Koa 中实现 chunked 数据传输

有关于 Transfer-Encoding:chunked 类型的响应,参见之前的文章HTTP 响应的分块传输。这里看 Koa 中如何实现。 Koa 中请求返回的处理 虽然官方文档有描述说明不建议直接调用 response.write: Bypassing Koas response handling is not supported. Avoid …

HTML5新特性之Mutation Observer

Mutation Observer(变动观察器)是监视DOM变动的接口。当DOM对象树发生任何变动时,Mutation Observer会得到通知。 要概念上,它很接近事件。可以理解为,当DOM发生变动会触发Mutation Observer事件。但是,它与…

Python操作MongoDB - 极简教程

2019独角兽企业重金招聘Python工程师标准>>> Python 连接 MongoDB 安装PyMongo模块 pip install pymongo使用MongoClient建立连接 from pymongo import MongoClient # 以下为三种建立连接的方式 #client MongoClient() #client MongoClient(localhost, 27017) #cl…

java 省市区三级联动_AJAX省市区三级联动下拉菜单(java版)

此小程序的功能主要是采用异步请求方式从数据库中调取省市区信息显示到下拉列表:代码如下:建立数据库中的代码和一些配置文件信息就省略了,主要有JavaScript中的代码为:$(document).ready(function(){$.get("getProvince.do&…

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结 教材学习内容总结 继承 继承就是避免多个类间重复定义共同行为。面向对象中,子类继承父类,就是把程序中相同的代码部分提升为父类。extends关键字,表示前者会扩充后者的行为&#xff…

【eclipse转idea的第一天】配置idea

为什么80%的码农都做不了架构师?>>> 导入maven项目 设置maven(全局) 为了不然才转idea的码友们重复我犯过的错,我这儿截图步骤说明下: 这里是列表文本这里是列表文本idea的设置有两种:全局,局部(我这么叫的…

Vmware 安装虚拟工具 (二)

打开虚拟机,以root超级用户登陆,菜单栏选择虚拟机,install安装虚拟机 拷贝虚拟工具到 在根目录下建立文件夹,并将工具拷贝到该文件夹,例如vmtool 打开终端,进入该目录开始安装 如图,进入目录解压…

git与svn的区别 ?Git 与 SVN那个更好?

git与svn的区别 : http://www.360doc.com/content/12/1228/20/11220452_256857021.shtml 在版本控制系统的选型上,是选择Git还是SVN? 对于开源项目来说这不算问题。使用Git极大地提高了开发效率、扩大了开源项目的参与度、 增强了版本控制系统…

利用Arcgis for javascript API绘制GeoJSON并同时弹出多个Popup

1.引言 由于Arcgis for javascript API不可以绘制Geojson,并且提供的Popup一般只可以弹出一个,在很多专题图制作中,会遇到不少的麻烦。因此本文结合了两个现有的Arcgis for javascript API扩充库,对其进行改造达到绘制Geojson并同…

HBase数据备份及恢复(导入导出)的常用方法

一、说明 随着HBase在重要的商业系统中应用的大量增加,许多企业需要通过对它们的HBase集群建立健壮的备份和故障恢复机制来保证它们的企业(数据)资产。备份Hbase时的难点是其待备份的数据集可能非常巨大,因此备份方案必须有很高的…

Android商城开发系列(二)——App启动欢迎页面制作

商城APP一般都会在应用启动时有一个欢迎界面,下面我们来实现一个最简单的欢迎页开发:就是打开商城App,先出现欢迎界面,停留几秒钟,自动进入应用程序的主界面。 首先先定义WelcomeActivity布局,布局非常简单…

DELL安装不了mysql_Windows 版本 Mysql 8.x 安装

1、官网下载安装包百度网盘链接:https://pan.baidu.com/s/1cFRbQM5720xrzMxbgjPeyA提取码:xlz72、解压安装包并新建一个文件夹作为安装目录(mysqlInstall)3、配置 Mysql 环境变量4、在解压好的目录下新建一个 my.ini 文件(注意:my.ini 文件和…