mysql是一种关系型数据库,关系型数据库一个重要的特性就是支持事务,这是区别于no-sql产品的一个核心特性。当然了,no-sql产品支持键值查询,不能支持sql语句,这也是一个区别。今天主要讨论下事务的提交流程,由于mysql插件式存储架构,导致开启binlog后,事务提交实质是二阶段提交,通过两阶段提交,来保证存储引擎和二进制日志的一致。本文仅讨论binlog未打卡状态下的提交流程,后续会讨论打开binlog选项后的提交逻辑。源码调试环境如下:

测试环境:
OS:windows
DB:mysql 5.6.12
engine:innodb
 
测试前置条件:
set autocommit=0;
create table tt(col1 int, col2 varchar(100));
 
测试语句:
insert into tt values(1, 'abcdef');
commit;
 
    无论对于dml语句【insert,update,delete等】还是dcl语句【commit,rollback】,mysql提供了公共接口mysql_execute_command,我们先分析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,这两个调用分别是语句级提交和语句级回滚。语句级提交,对于非自动模式提交情况下,主要作两件事情,一是释放autoinc锁,这个锁主要用来处理多个事务互斥地获取自增列值,因此,无论最后该语句提交或是回滚,该资源都是需要而且可以立马放掉的。二是标识语句在事务中位置,方便语句级回滚。执行commit后,可以进入commit流程,现在来看看具体事务提交的流程是怎样的。

mysql_execute_command
trans_commit
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)是一种实现事务日志的标准方法,具体而言就是修改记录前,一定要先写日志;事务提交过程中,一定要保证日志先落盘,才能算事务提交完成。通过WAL方式,在保证事务特性的情况下,可以提交数据库的性能。从上述流程可以看出,提交过程中,主要做了4件事情,首先是清理undo段信息,对于innodb存储引擎的更新操作来说,undo段需要purge,这里的purge主要职能是,真正删除物理记录。在执行delete或update操作时,实际旧记录没有真正删除,只是在记录上打了一个标记,而是在事务提交后,purge线程真正删除,释放物理页空间。因此,提交过程中会将undo信息加入purge列表,供purge线程处理。然后是释放锁资源,mysql通过锁互斥机制保证不同事务不同时操作一条记录,事务执行后才会真正释放所有锁资源,并唤醒等待其锁资源的其他事务;再就是刷redo日志,前面我提到了,mysql实现事务一致性和持久性的机制。通过redo日志落盘操作,保证了即使修改的数据页没有即使更新到磁盘,只要日志是完成了,就能保证数据库的完整性和一致性;最后就是清理保存点列表,每个语句实际都会有一个savepoint(保存点),保存点作用是为了可以回滚到事务的任何一个语句执行前的状态,由于事务都已经提交了,所以保存点列表可以被清理了。

     关于里面提到的mysql的锁机制,purge原理,redo日志,undo段等内容,其实都是数据库的核心,里面内容也很多,后面学习研究后再给大家分享。后面附录是有关事务的关键数据结构及其成员。
struct trx_t{

        trx_rseg_t*	rseg;		/*!< rollback segment assigned to the
transaction, or NULL if not assigned trx_undo_t* insert_undo; /*!< pointer to the insert undo log, or
NULL if no inserts performed yet */
trx_undo_t* update_undo; /*!< pointer to the update undo log, or
NULL if no update performed yet */
const char* mysql_log_file_name;
/*!< if MySQL binlog is used, this field
contains a pointer to the latest file
name; this is NULL if binlog is not
used */
ib_int64_t mysql_log_offset;
/*!< if MySQL binlog is used, this
field contains the end offset of the
binlog entry */
} /* The rollback segment memory object */
struct trx_rseg_t{
/* Fields for update undo logs */
UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_list;
/* List of update undo logs */
UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_cached;
/* List of update undo log segments
cached for fast reuse */
/*--------------------------------------------------------*/
/* Fields for insert undo logs */
UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_list;
/* List of insert undo logs */
UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_cached;
/* List of insert undo log segments
cached for fast reuse */
}

  

 
 
 
 

 

 
 
 

mysql源码解读之事务提交过程(一)的更多相关文章

  1. mysql源码解读之事务提交过程(二)

    上一篇文章我介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称 ...

  2. mysql源码解读之配置文件

    要研究mysql,最好的资源莫过于源码了,所以本人打算通过调试源码的方式来深入理解mysql的点点滴滴.搭建mysql调试环境很简单,从官方下载mysql源码,利用cmake工具生成工程即可.为了方便 ...

  3. MySQL源码之两阶段提交

    在双1的情况下,两阶段提交的过程 环境准备:mysql 5.5.18, innodb 1.1 version配置: sync_binlog=1 innodb_flush_log_at_trx_comm ...

  4. .NET框架源码解读之SSCLI编译过程简介

    前文演示了编译SSCLI最简便的方法(在Windows下): 在“Visual Studio 2005 Command Prompt”下,进入SSCLI的根目录: 运行 env.bat 脚本准备环境: ...

  5. storm源码分析之topology提交过程

    storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...

  6. Python Web Flask源码解读(三)——模板渲染过程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  7. mybatis源码解读(四)——事务的配置

    上一篇博客我们介绍了mybatis中关于数据源的配置原理,本篇博客介绍mybatis的事务管理. 对于事务,我们是在mybatis-configuration.xml 文件中配置的: 关于解析 < ...

  8. MYSQL 源码解读系列 [线程池。。] ----dennis的博客

    http://blog.sina.com.cn/s/articlelist_1182000643_0_1.html

  9. AFNetworking 3.0 源码解读 总结(干货)(上)

    养成记笔记的习惯,对于一个软件工程师来说,我觉得很重要.记得在知乎上看到过一个问题,说是人类最大的缺点是什么?我个人觉得记忆算是一个缺点.它就像时间一样,会自己消散. 前言 终于写完了 AFNetwo ...

随机推荐

  1. WCF学习笔记1--发布使用配置文件的服务

    关于WCF的入门网上资料很多,可以参考蒋金楠老师的博客http://www.cnblogs.com/artech/archive/2007/02/26/656901.html,我是从这篇博客开始学习的 ...

  2. 孙鑫MFC学习笔记13:文档

    1.CArchive类保存内存数据 2.CAchive类重载了>>与<<操作符,类似C++文件流 3.在OnNewDocument中通过SetTitle设置标题 4.字符串资源 ...

  3. 孙鑫MFC学习笔记9:状态栏与工具栏编程

    1.在窗口创建之前就应该修改窗口的样式 2.单文档应用程序会把文档名作为应用程序标题,应该去掉FWS_ADDTOTITLE属性,然后修改lpszName为标题 3.在窗口创建完成后,可以通过SetWi ...

  4. 修正 XE6 TListView 上方 SearchBok 右边的清除钮显示

    注意:XE7 已修正这个问题. Delphi Firemonkey TListView 提供了搜寻的功能,但在 XE6 以前的版本,可以显示右边的清除按钮,在 XE6 确消失了,这里提供一个修正的方案 ...

  5. PHP内核探索之变量(4)- 数组操作

    上一节(PHP内核探索之变量(3)- hash table),我们已经知道,数组在PHP的底层实际上是HashTable(链接法解决冲突),本文将对最常用的函数系列-数组操作的相关函数做进一步的跟踪. ...

  6. Oracle 免费的数据库--Database 快捷版 11g 安装使用与"SOD框架"对Oracle的CodeFirst支持

    一.Oracle XE 数据库与连接工具安装使用 Oracle数据库历来以价格昂贵出名,当然贵有贵的道理,成为一个Oracle DBA也是令人羡慕的事情,如果程序员熟悉Oracle使用也有机会接触到大 ...

  7. Linux学习笔记15-YUM安装

    rpm软件包缺点:需要手工解决软件包的依赖关系.使用YUM可解决该问题. YUM(Yellodog Updater, Modified)是一个RPM前端程序,主要目的是设计用来自动解决RPM的依赖关系 ...

  8. c#事务用法

    ado.net2.0的SqlTransaction使用方法 /////ado.net1.0中使用Transacation(事务) string connectionString = "dat ...

  9. WPF如何实现一款类似360安全卫士界面的程序?(共享源码!)

    以前学习Windows Form编程的时候,总感觉自己做的界面很丑,看到360安全卫士.迅雷等软件的UI设计都非常美观,心里总是憧憬着要是自己能实现这样的UI效果该多好!!!另一个困扰我的问题是,这个 ...

  10. bootstrap字体图标在谷歌显示正常,在火狐显示异常的问题

    bootstrap字体图标的使用 现在有很多的网站支持字体图标,我所知道的有bootstrap,fontawesome,iconmoon,等等,可能还有其他我并不知道 bootstrap只要你的文件夹 ...