- 浏览: 2261553 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (423)
- FileNet相关 (3)
- 应用服务器相关 (22)
- Java综合 (77)
- 持久层 (24)
- struts (11)
- webservice (8)
- 虚拟机 (2)
- 光盘刻录 (0)
- AD及AD集群 (1)
- JS (33)
- F5 (0)
- loadrunner8.1 (0)
- Java 反编译工具 (2)
- DataBase (62)
- ant (1)
- 操作系统 (29)
- 我的任务 (3)
- 平台架构 (16)
- 业务规则引擎 (2)
- 模板 (1)
- EJB (5)
- spring (24)
- CMMI (1)
- 项目管理 (20)
- LDAP (13)
- JMS (10)
- JSP (19)
- JBPM (2)
- web MVC框架设计思想 (2)
- 第三方支付平台 (2)
- BUG管理工具 (1)
- 垃圾站 (2)
- php (1)
- swing (1)
- 书籍 (1)
- QQ qq (2)
- 移动互联网 (26)
- 爱听的歌曲 (0)
- hadoop (4)
- 数据库 (9)
- 设计模式 (1)
- 面试经验只谈 (1)
- 大数据 (9)
- sp (1)
- 缓存数据库 (8)
- storm (2)
- taobao (2)
- 分布式,高并发,大型互联网,负载均衡 (6)
- Apache Ignite (0)
- Docker & K8S (0)
最新评论
-
wangyudong:
新版本 Wisdom RESTClienthttps://gi ...
spring rest mvc使用RestTemplate调用 -
wangyudong:
很多API doc生成工具生成API文档需要引入第三方依赖,重 ...
spring rest mvc使用RestTemplate调用 -
zhaoshijie:
cfying 写道大侠,还是加载了两次,怎么解决啊?求。QQ: ...
spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件) -
xinglianxlxl:
对我有用,非常感谢
spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件) -
k_caesar:
多谢,学习了
利用maven的resources、filter和profile实现不同环境使用不同配置文件
关键字:mysql源码解读之事务提交过程--第二篇
上一篇文章我介绍了在关闭binlog的情况下,事务提交的大概流程。之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。内部xa事务我理解主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog在mysql层,而redo log 在存储引擎层);而外部xa事务则是指支持多实例分布式事务,这个才算是真正的分布式事务。既然是xa事务,必然涉及到两阶段提交,对于内部xa而言,同样存在着提交的两个阶段。下文会结合源码详细解读内部xa的两阶段提交过程,以及各种情况下,mysqld crash后,mysql如何恢复来保证事务的一致性。
测试环境:
OS:windows
DB:mysql 5.6.12
engine:innodb
配置文件参数:
log-bin=D:\chuck\mysql\log\5-6-12\mysql-bin
binlog_format=ROW
set autocommit=0;
sync_binlog=1;
innodb_flush_log_at_trx_commit=1;
innodb_support_xa=1;
测试前置条件:
create table tt(col1 int, col2 varchar(100));
测试语句:
insert into tt values(1, 'abcdef');
commit;
打开binlog选项后,执行事务提交命令时,就会进入两阶段提交模式。两阶段提交分为prepare阶段和commit两个阶段。流程如下 :这里面涉及到两个重要的参数:innodb_flush_log_at_trx_commit和sync_binlog,参数可以设置不同的值,具体可以查看mysql的帮助手册。我这里设置的是双一模式(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日志也会刷入】
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调用
下面这部分是我抽象出来的源码调用部分,大家可以通过单步调试方式,在关键函数中设置断点,来详细了解这个过程。
===========
prepare阶段
===========
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阶段
============
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也有可能出现问题,另外若机器掉电,mysqld也会同样挂掉。但是即使这样,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_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的情况下,事务提交的大概流程。之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。内部xa事务我理解主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog在mysql层,而redo log 在存储引擎层);而外部xa事务则是指支持多实例分布式事务,这个才算是真正的分布式事务。既然是xa事务,必然涉及到两阶段提交,对于内部xa而言,同样存在着提交的两个阶段。下文会结合源码详细解读内部xa的两阶段提交过程,以及各种情况下,mysqld crash后,mysql如何恢复来保证事务的一致性。
测试环境:
OS:windows
DB:mysql 5.6.12
engine:innodb
配置文件参数:
log-bin=D:\chuck\mysql\log\5-6-12\mysql-bin
binlog_format=ROW
set autocommit=0;
sync_binlog=1;
innodb_flush_log_at_trx_commit=1;
innodb_support_xa=1;
测试前置条件:
create table tt(col1 int, col2 varchar(100));
测试语句:
insert into tt values(1, 'abcdef');
commit;
打开binlog选项后,执行事务提交命令时,就会进入两阶段提交模式。两阶段提交分为prepare阶段和commit两个阶段。流程如下 :这里面涉及到两个重要的参数:innodb_flush_log_at_trx_commit和sync_binlog,参数可以设置不同的值,具体可以查看mysql的帮助手册。我这里设置的是双一模式(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日志也会刷入】
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调用
下面这部分是我抽象出来的源码调用部分,大家可以通过单步调试方式,在关键函数中设置断点,来详细了解这个过程。
===========
prepare阶段
===========
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阶段
============
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也有可能出现问题,另外若机器掉电,mysqld也会同样挂掉。但是即使这样,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_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
发表评论
-
性能优化重要的mysql profile功能
2023-02-24 23:24 234关键字:性能优化重要的mysql profile功能 ... -
mysql源码解读之事务提交过程--第一篇
2018-01-10 14:50 1525关键字:mysql源码解读之事务提交过程--第一篇 mys ... -
循环创建多张表 和 多个数据库sql语句(数据库水平分库分表时方便)
2016-03-04 12:58 12384关键字:循环创建多张 ... -
高可用、开源的Redis缓存集群方案
2015-04-16 12:25 3758推荐综合架构交流群:J ... -
Oracle实现类split函数的方
2015-04-16 10:10 642关键字:Oracle实现类split函数的方 项目里需要保存结 ... -
各种Nosql数据库系统对比及应用场景分析
2015-04-15 16:29 756关键字:各种Nosql数据库系统对比及应用场景分析 导读:Kr ... -
数据库迁移之从oracle 到 MySQL
2015-04-11 09:38 916关键字:数据库迁移之从oracle 到 MySQL 开场白: ... -
Mongodb命令大全
2015-03-18 11:18 803关键字:Mongodb命令大全 他支持的数据结构非常松散,是类 ... -
MongoDB中缩减Shard集群(删除一个Shard)--删除一个分片
2015-03-13 12:29 3641关键字:MongoDB中缩减Shard集群(删除一个Shard ... -
Mongodb副本集(三个节点:一主一从一仲裁)-配置文件方式启动
2015-03-05 17:32 2072关键字:Mongodb副本集(三个节点:一主一从一仲裁)-配置 ... -
mongodb 数据库操作--备份 还原 导出 导入
2015-03-02 17:17 2188关键字:mongodb 数据库 ... -
win7 64位的数据源(ODBC)配置问题
2015-01-20 16:36 1078关键字:win7 64位的数据源(ODBC)配置问题 ... -
MongoDB spring 整合封装
2015-01-06 21:43 494关键字:MongoDB spring 整合封装 htt ... -
数据库连接池选型
2014-12-04 18:32 1171关键字:数据库连接池选型 proxool(与spring不太 ... -
atomikos(com.atomikos.icatch.SysException: Error in init(): Log already in use)
2014-10-15 13:12 8528关键字:atomikos(com.atomikos.icatc ... -
Mysql高可用架构
2014-09-02 11:41 2800关键字:Mysql高可用架构 最近花了点时间研究了一下mys ... -
MySQL原生HA方案 – Fabric体验之旅
2014-08-21 13:13 7109关键字:MySQL原生HA方案 – Fabric体验之旅 ta ... -
Windows下MySQL多实例运行
2014-08-21 10:09 6093关键字:Windows下MySQL多 ... -
性能优化重要的mysql profile功能
2014-02-10 15:25 51关键字:性能优化重要的mysql profile功能 my ... -
mysql profile功能
2014-02-10 15:12 24关键字:mysql profile功能 mysql的sql ...
相关推荐
4. **源码解读** 源码数据库通常包含Java源代码、配置文件、数据库脚本等。源码分析可以帮助我们理解业务逻辑、数据流向以及框架配置。例如,Controller类处理HTTP请求,Service类封装业务逻辑,DAO层与数据库交互...
第2章则详细阐述了MySQL中的各种数据类型,如数值类型(BIT、TINYINT、BOOL等)、字符串类型(CHAR、VARCHAR等)、日期和时间类型(DATE、TIME、DATETIME等),这些数据类型的选择直接影响到数据库的设计和性能。...
本篇文章将详细解读一个基于SSM(Spring、SpringMVC、MyBatis)和MySQL数据库的娱乐影视公司管理系统源码数据库,这是一份适用于毕业设计的优秀案例,对于学习Java Web开发的学生以及初入行业的开发者具有很高的参考...
四、源码解读 源码中常见的关键组件包括: 1. 用户认证模块:实现用户登录、注册、权限验证等功能。 2. 数据操作模块:处理数据库CRUD(创建、读取、更新、删除)操作。 3. 业务逻辑模块:封装具体业务规则,如绩效...
"精选_基于JSP和MySql的在线电子书商城_源码打包"这个标题揭示了我们讨论的核心内容是一个完整的项目源码,它是一个在线电子书商城的实现,采用Java的Web开发技术JSP(JavaServer Pages)和关系型数据库MySQL。...
2. **数据库设计**:使用MySQL或其他数据库管理系统存储商品信息、订单、用户数据等,涉及SQL查询、事务处理、索引优化等知识。 3. **前端技术**:包括HTML、CSS和JavaScript,用于构建用户友好的交互界面,可能...
- JDBC 默认情况下每个 SQL 语句都是一个独立的事务,即每次执行完 SQL 语句后都会自动提交。 - 这意味着,如果不显式开启事务管理,每次执行 SQL 语句时都会立即生效。 **8.3 事务提交与回滚** - 通过 `Connection...
在SQL性能调整领域,优化数据库查询是至关重要的。...以上就是对"sql性能的调整-总结"的详细解读,涵盖了从索引优化到源码调整的多个层面,通过这些方法可以显著提高SQL查询效率,进而提升整个数据库系统的性能。
以下将对该课程可能涵盖的一些核心知识点进行详细解读,并结合Web开发领域的常见技术栈来进行拓展说明。 ### 一、Web基础知识 #### 1. HTML5 - **定义与作用**:HTML(Hyper Text Markup Language)是构成网页的...
2. **数据库交互**:PHP常与MySQL等数据库系统配合,处理用户注册、登录、商品浏览、购物车、订单处理等数据操作。这涉及到SQL查询和事务处理。 3. **session和cookie管理**:为了跟踪用户状态,PHP会利用session和...
2. SSM框架:SSM是Java Web开发中常用的三层架构,包括Spring(负责依赖注入和事务管理)、SpringMVC(处理HTTP请求和视图渲染)和MyBatis(数据库操作)。理解这三个框架的集成和工作原理,以及如何配置和调用,是...
"JAVA网上商城源码"指的是基于Java编程语言开发的电子商务平台的原始代码,这通常包括了服务器端、客户端以及数据库交互等核心功能。"Java购物系统"进一步明确了这是一个用于在线购物的软件系统,具备商品展示、用户...
2. **数据库相关** - 这个标签强调了 Ehlib 的核心功能,即提供数据库访问接口,支持多种数据库引擎,如 SQL Server、Oracle、MySQL 等,提供了丰富的数据库操作方法和事务处理能力。 3. **源码** - 提供源代码意味...
以上是Spring+Hibernate将文件二进制数据持久化到数据库的解决方案,而Struts通过将表单中file类型的组件映射为ActionForm中类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。 工程...
本资源包含七个优秀的Java毕业设计案例,涵盖了不同的应用场景,下面将对这些案例进行详细解读。 1. **网上银行系统**:这是一个模拟真实银行服务的应用程序,包括用户注册、登录、存款、取款、转账等功能。设计这...
这篇博文(虽然链接已不可用)可能提供了关于该项目的详细解读,帮助读者理解如何从零开始搭建一个类似的在线购物平台。 在电商网站开发中,以下几个关键知识点是不可或缺的: 1. **前端框架**:吉淘网站可能采用...