1024MySQL事物提交机制
转自 http://www.cnblogs.com/exceptioneye/p/5451960.html
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)
{
case SQLCOM_INSERT:
mysql_insert();
break;
case SQLCOM_UPDATE:
mysql_update();
break;
case SQLCOM_DELETE:
mysql_delete();
break;
......
}
if thd->is_error() //语句执行错误
trans_rollback_stmt(thd);
else
trans_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();
<span style="color: #ff0000;">trx_commit</span>(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 事务)的方式完成两阶段提交。
参考
1、《高性能MySQL》
1024MySQL事物提交机制的更多相关文章
- innodb二阶段日志提交机制和组提交解析
前些天在查看关于innodb_flush_log_at_trx_commit的官网解释时产生了一些疑问,关于innodb_flush_log_at_trx_commit参数的详细解释参见官网: htt ...
- MysqL自动提交机制的关闭
MysqL在执行一句数据库操作命令的时候,通常都是自动提交的.常用引擎下有两种,分别是MyIsam和InnoDB,MyIsam是不支持事务处理的,但InnoDB支持,但InnoDB在不开启事务处理的情 ...
- Spring对Hibernate的session生效期(事物提交管理)介绍
在Hibernate中我们每次进行一个操作的的时候我们都是要先开启事务,然后进行数据操作,然后提交事务,关闭事务,这样做的原因是因为Hibernate默认的事务自动提交是false,它是需要人为的手动 ...
- spring事物传播机制 事物隔离级别
Spring事务类型详解: PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SUPPORTS--支持当前事务,如 ...
- Redis集群事物提交异常Multi-key operations must involve a single slot
redis做完集群后不同键在同一事物中提交,因为key的hash计算结果不同不能分配到同一个分片上,因此出现此异常. 解决方案:在本次事物的key内添加"{tag}",这时redi ...
- Spring事物管理机制简单学习
首先spring并不直接管理事物,而是提供了多种事物管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现. Spring管理事物的接口是org.s ...
- spring事物传播机制与隔离级别
转载自:http://www.blogjava.net/freeman1984/archive/2010/04/28/319595.html7个传播行为,4个隔离级别, Spring事务的传播行为和隔 ...
- PDO的事物处理机制
Mysql的事务处理: 1.MySQL目前只有InnoDB 和BDB两个数据表类型才支持事务. 2.在默认条件下,MySQL是以自动提交(autocommit)模式运行的,这就意味着所执行的每一个语句 ...
- ADF一个EO的事物提交周期
客户端通过传递键对象调用实体定义的findByPrimaryKey(),获得EO.ADF框架首先检查实体缓存, 如果在实体缓存中没有找到实体,就执行SQL SELECT查询,从数据库读取行.示例如下: ...
随机推荐
- Java DualPivotQuickSort 双轴快速排序 源码 笔记
DualPivotQuicksort source code 这个算法是Arrays.java中给基本类型的数据排序使用的具体实现.它针对每种基本类型都做了实现,实现的方式有稍微的差异,但是思路都是相 ...
- 在linux下如何使用yum查看安装了哪些软件包
$yum list installed //列出所有已安装的软件包 yum针对软件包操作常用命令: 1.使用YUM查找软件包 命令:yum search 2.列出所有可安装的软件包 命令:yum li ...
- java并发编程基础 --- 7章节 java中的13个原子操作类
当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量 i=1,A线程更新 i+1,B线程也更新 I+1,经过两个线程的操作之后可能 I不等于3,而是等于2.因为A和B线程更 ...
- jmeter连接Mysql数据库测试性能初探
Jmeter mysql性能测试演示 1. Jmeter是java开发的,jmeter连接mysql数据库当然需要jdbc驱动,这个可以在网上下载mysql-connector-java包,然后解压 ...
- 查看Linux内核版本之lsb_release
lsb_release命令LSB是Linux Standard Base的缩写,lsb_release命令用来显示LSB和特定版本的相关信息,可通过yum -y install redhat-lsb命 ...
- vs运行单个cpp文件
打开vs,新建项目,左侧win32见上图,右侧 win32控制台应用程序,填好名称后,确定----下一步,如下图,空项目 紧接着如下图,通过现有项添加自己的cpp文件,便可以运行了
- [日常] 最近的一些破事w...
更新博文一篇以示诈尸(大雾 (其实只是断了个网然后就彻底失踪了一波w...连题解都没法写了QAQ) $ \tiny{诈尸的实际情况是老姚提前走还把十一机房门锁了然而钥匙在联赛的时候就还了于是并不能进去 ...
- swift textview禁止用户使用复制粘贴
//自定义一个TextView class Own_TextView: UITextView { override func caretRect(for position: UITextPositio ...
- 使用Dockerfile创建一个tomcat镜像,并运行一个简单war包
docker已经看了有一段时间了,对镜像和容器也有了一个大致了解,参考书上的例子制作一个tomcat镜像,并简单运行一个HelloWorld.war 1.首先下载linux环境的tomcat和jdk, ...
- jav音频格式转换 ffmpeg 微信录音amr转mp3
项目背景: 之前公司开发了一个微信公众号,要求把js-sdk录音文件在web网页也能播放.众所周知,html的<audio>标签ogg,mp3,wav,也有所说苹果safari支持m4a格 ...