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,一经查实,立即删除!

相关文章

spray.json_如何使用Spray-json(Un)在Akka HTTP中封送JSON

spray.jsonby Miguel Lopez由Miguel Lopez 如何使用Spray-json(Un)在Akka HTTP中封送JSON (How to (Un)marshal JSON in Akka HTTP with spray-json) In the previous post, we added JSON support to our Akka HTTP API using circe.在上一篇文章中 ,我们使用circ…

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

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

input file 文件上传,js控制上传文件的大小和格式

文件上传一般是用jquery的uploadify,比较好用。后面会出文章介绍uploadify这个插件。 但是,有时候为了偷懒,直接就用input 的file进行文件和图片等的上传,input file 可以控制上传的格式,但是是html5,很多浏…

leetcode面试题 17.08. 马戏团人塔(二分法)

有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上。出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一点。已知马戏团每个人的身高和体重,请编写代码计算叠罗汉最多能叠几个人。 示例: 输入:…

如何选择适合自己的CMS建站系统

如今做网站已不像过去那样必须找网站公司才能建,因为网上针对建站的各种CMS建站系统层出不穷。像PageAdmin、DEDECMS、帝国CMS、Discuz等,这些CMS系统各有各的特点和优势,小熊优化的小编我从事网站制作和网站优化多年,和很多建站朋…

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

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

数据处理不等式:Data Processing Inequality

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

aws架构_如何使用AWS构建可扩展架构

aws架构What I learned building the StateOfVeganism ?我学到的建立素食主义的方法是什么? By now, we all know that news and media shape our views on the topics we discuss. Of course, this is different from person to person. Some might be influence…

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环境…

leetcode面试题 10.03. 搜索旋转数组(二分法)

搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。 示例1: 输入…

MSSQL → 02:数据库结构

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

JAVA拳皇_拳皇(Java简单的小程序)代码实例|chu

刚开始学习Java,看完老九君的视频根据他的内容敲的代码,感觉还挺有成就感的,毕竟刚学习Java。package helloasd;import java.util.*; public class hellojava { public static void main(String[] args) { Scanner input new Scanner(System…

mySQL教程 第9章 触发器

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

vue使用python_如何使用Python和Vue创建两人游戏

vue使用pythonby Neo Ighodaro由新Ighodaro 如何使用Python和Vue创建两人游戏 (How to create a two-player game with Python and Vue) In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game wi…

掩码图制作photoshop__新手用

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

leetcode287. 寻找重复数(二分法)

给定一个包含 n 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 示例 1: 输入: [1,3,4,2,2] 输出: 2 代码 class Solution {…

os-enviroment

pip3 install PyUserInput ping 是不带协议的转载于:https://www.cnblogs.com/liuweimingcprogram/p/10957592.html

java 压缩 乱码_如何解决java压缩文件乱码问题

用java来打包文件生成压缩文件,有两个地方会出现乱码:内容的中文乱码问题:修改sun的源码。使用开源的类库org.apache.tools.zip.ZipOutputStream和org.apache.tools.zip.ZipEntry,这两个类ant.jar中有,可以下载使用即可…

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

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

TensorFlow 学习(十)—— 工具函数

1. 基本 tf.clip_by_value() 截断,常和对数函数结合使用 # 计算交叉熵crose_ent -tf.reduce_mean(tf.log(y_*tf.clip_by_value(y, 1e-10, 1.))) a tf.reshape(tf.range(6, dtypetf.float32), [2, 3]) tf.clip_by_value(a, 2.5, 4.5) # 将值限定在 2.5 …