【MYSQL】两阶段提交及相关参数介绍
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,由于Mysql的事务日志包含二进制日志和存储引擎日志,当发生崩溃恢复时,MySQL主节点通过redo log进行恢复,而在主从复制的环境下,slaver节点是依据于主节点的binlog进行同步数据的;
千家信息网最后更新 2025年02月01日【MYSQL】两阶段提交及相关参数介绍由于Mysql的事务日志包含二进制日志和存储引擎日志,当发生崩溃恢复时,MySQL主节点通过redo log进行恢复,而在主从复制的环境下,slaver节点是依据于主节点的binlog进行同步数据的;这样的架构于是对mysql的二进制日志和redo log,就有两个基本要求:第一,保证binlog里面存在的事务一定在redo log里面存在,也就是binlog里不会比redo log多事务(可以少,因为redo log里面记录的事务可能有部分没有commit,这些事务最终可能会被rollback)。 2、顺序一致,这也是很重要的一点,假设两者记录的事务顺序不一致,那么会出现类似于主库事务执行的顺序是ta, tb, tc,td,但是binlog里面记录的是ta,tc, tb, td,binlog复制到从库后导致主从的数据不一致。为了达到上面说的两点,mysql是怎么来实现的呢?没错,答案是内部xa事务(核心是2pc)
一、二阶段事务提交流程:
(1)先调用binglog_hton和innobase_hton的prepare方法完成第一阶段,binlog_hton的papare方法实际上什么也没做,innodb的prepare将事务状态设为TRX_PREPARED,并将redo log刷磁盘
(2)如果事务涉及的所有存储引擎的prepare都执行成功,则调用TC_LOG_BINLOG::log_xid将SQL语句写到binlog,此时,事务已经铁定要提交了。否则,调用ha_rollback_trans回滚事务,而SQL语句实际上也不会写到binlog。
(3)最后,调用引擎的commit完成事务的提交。实际上binlog_hton->commit什么也不会做(因为(2)已经将binlog写入磁盘),innobase_hton->commit则清除undo信息,刷redo日志,将事务设为TRX_NOT_STARTED状态
二、事务恢复流程:
Innodb在恢复的时候,不同状态的事务,会进行不同的处理(见trx_rollback_or_clean_all_without_sess函数):
<1>对于TRX_COMMITTED_IN_MEMORY的事务,清除回滚段,然后将事务设为TRX_NOT_STARTED;
<2>对于TRX_NOT_STARTED的事务,表示事务已经提交,跳过;
<3>对于TRX_PREPARED的事务,要根据binlog来决定事务的命运,暂时跳过;
<4>对于TRX_ACTIVE的事务,回滚。
简单来讲,当发生崩溃恢复时,数据库根据redo log进行数据恢复,逐个查看每条redo的事务状态,如果根据上图流程,已进行到TRX_NOT_STARTED阶段,也就是存储引擎commit阶段,那么说明redo log和bin log是一致的,正常根据redo进行恢复即可;事务状态为TRX_ACTIVE,不用说了,都没写到binlog中,直接回滚;但如果事务状态为TRX_PREPARED,就要分两种情况了,要先检查binlog是否已写入成功?如果没写入成功,那么就算是TRX_PREPARED状态,也要回滚。如果写入成功了,那么就进行最后一步,调用存储引擎commit,更改事务状态为TRX_NOT_STARTED,也就是真正提交状态,可以用作数据恢复。
从以上分析可以看出,写binlog是一定已经提交的数据,只要写了binlog,事务是铁定要提交成功的。因为主从复制环境下,写了binlog就可能直接传输到从节点应用了,所以两阶段提交很好的保持数据一致性和顺序性
三、相关参数介绍:
1、innodb_support_xa
用于控制innodb是否支持XA事务的2PC,默认是TRUE。如果关闭,则innodb在prepare阶段就什么也不做;这可能会导致binlog的顺序与innodb提交的顺序不一致(比如A事务比B事务先写binlog,但是在innodb内部却可能A事务比B事务后提交),这会导致在恢复或者slave产生不同的数据。
2、sync_binlog
Mysql在提交事务时调用MYSQL_LOG::write完成写binlog,并根据sync_binlog决定是否进行刷盘。默认值是0,即不刷盘,从而把控制权让给OS。如果设为1,则每次提交事务,就会进行一次刷盘;这对性能有影响(5.6已经支持binlog group),所以很多人将其设置为100。
3、innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit有0、1、2三个值分别代表不同的使redo log落地策略。0表示每秒进行一次flush,但是每次事务commit不进行任何操作(每秒调用fsync使数据落地到磁盘,不过这里需要注意如果底层存储有cache,比如raid cache,那么这时也不会真正落地,但是由于一般raid卡都带有备用电源,所以一般都认为此时数据是安全的)。1代表每次事务提交都会进行flush,这是最安全的模式。2表示每秒flush,每次事务提交时不flush,而是调用write将redo log buffer里面的redo log刷到os page cache。
那现在来比较三种策略的优劣势:1由于每次事务commit都会是redo log落地所以是最安全的,但是由于fsync的次数增多导致性能下降比较厉害。0表示每秒flush,每次事务提交不进行任何操作,所以mysql crash或者os crash时会丢失一秒的事务。2相对于0来说了多了每次事务commit时会有一次write操作,此时数据虽然没有落地到磁盘但是只要没有 os crash,即使mysql crash,那么事务是不会丢失的。2相对于0来说会稍微安全一点点。
上面3个参数不同的值会带来不同的效果。三者都设置为1(TRUE),数据才能真正安全。sync_binlog非1,可能导致binlog丢失(OS挂掉),从而与innodb层面的数据不一致。innodb_flush_log_at_trx_commit非1,可能会导致innodb层面的数据丢失(OS挂掉),从而与binlog不一致
一、二阶段事务提交流程:
(1)先调用binglog_hton和innobase_hton的prepare方法完成第一阶段,binlog_hton的papare方法实际上什么也没做,innodb的prepare将事务状态设为TRX_PREPARED,并将redo log刷磁盘
(2)如果事务涉及的所有存储引擎的prepare都执行成功,则调用TC_LOG_BINLOG::log_xid将SQL语句写到binlog,此时,事务已经铁定要提交了。否则,调用ha_rollback_trans回滚事务,而SQL语句实际上也不会写到binlog。
(3)最后,调用引擎的commit完成事务的提交。实际上binlog_hton->commit什么也不会做(因为(2)已经将binlog写入磁盘),innobase_hton->commit则清除undo信息,刷redo日志,将事务设为TRX_NOT_STARTED状态
二、事务恢复流程:
Innodb在恢复的时候,不同状态的事务,会进行不同的处理(见trx_rollback_or_clean_all_without_sess函数):
<1>对于TRX_COMMITTED_IN_MEMORY的事务,清除回滚段,然后将事务设为TRX_NOT_STARTED;
<2>对于TRX_NOT_STARTED的事务,表示事务已经提交,跳过;
<3>对于TRX_PREPARED的事务,要根据binlog来决定事务的命运,暂时跳过;
<4>对于TRX_ACTIVE的事务,回滚。
简单来讲,当发生崩溃恢复时,数据库根据redo log进行数据恢复,逐个查看每条redo的事务状态,如果根据上图流程,已进行到TRX_NOT_STARTED阶段,也就是存储引擎commit阶段,那么说明redo log和bin log是一致的,正常根据redo进行恢复即可;事务状态为TRX_ACTIVE,不用说了,都没写到binlog中,直接回滚;但如果事务状态为TRX_PREPARED,就要分两种情况了,要先检查binlog是否已写入成功?如果没写入成功,那么就算是TRX_PREPARED状态,也要回滚。如果写入成功了,那么就进行最后一步,调用存储引擎commit,更改事务状态为TRX_NOT_STARTED,也就是真正提交状态,可以用作数据恢复。
从以上分析可以看出,写binlog是一定已经提交的数据,只要写了binlog,事务是铁定要提交成功的。因为主从复制环境下,写了binlog就可能直接传输到从节点应用了,所以两阶段提交很好的保持数据一致性和顺序性
三、相关参数介绍:
1、innodb_support_xa
用于控制innodb是否支持XA事务的2PC,默认是TRUE。如果关闭,则innodb在prepare阶段就什么也不做;这可能会导致binlog的顺序与innodb提交的顺序不一致(比如A事务比B事务先写binlog,但是在innodb内部却可能A事务比B事务后提交),这会导致在恢复或者slave产生不同的数据。
2、sync_binlog
Mysql在提交事务时调用MYSQL_LOG::write完成写binlog,并根据sync_binlog决定是否进行刷盘。默认值是0,即不刷盘,从而把控制权让给OS。如果设为1,则每次提交事务,就会进行一次刷盘;这对性能有影响(5.6已经支持binlog group),所以很多人将其设置为100。
3、innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit有0、1、2三个值分别代表不同的使redo log落地策略。0表示每秒进行一次flush,但是每次事务commit不进行任何操作(每秒调用fsync使数据落地到磁盘,不过这里需要注意如果底层存储有cache,比如raid cache,那么这时也不会真正落地,但是由于一般raid卡都带有备用电源,所以一般都认为此时数据是安全的)。1代表每次事务提交都会进行flush,这是最安全的模式。2表示每秒flush,每次事务提交时不flush,而是调用write将redo log buffer里面的redo log刷到os page cache。
那现在来比较三种策略的优劣势:1由于每次事务commit都会是redo log落地所以是最安全的,但是由于fsync的次数增多导致性能下降比较厉害。0表示每秒flush,每次事务提交不进行任何操作,所以mysql crash或者os crash时会丢失一秒的事务。2相对于0来说了多了每次事务commit时会有一次write操作,此时数据虽然没有落地到磁盘但是只要没有 os crash,即使mysql crash,那么事务是不会丢失的。2相对于0来说会稍微安全一点点。
上面3个参数不同的值会带来不同的效果。三者都设置为1(TRUE),数据才能真正安全。sync_binlog非1,可能导致binlog丢失(OS挂掉),从而与innodb层面的数据不一致。innodb_flush_log_at_trx_commit非1,可能会导致innodb层面的数据丢失(OS挂掉),从而与binlog不一致
事务
数据
状态
一致
阶段
不同
顺序
安全
成功
引擎
日志
存储
落地
磁盘
节点
主从
也就是
实际
实际上
流程
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
机械软件开发使用方法
千尺下载软件开发
鲲鹏服务器浙江移动
工控网络安全竞赛 赛题类型
数据库时间与客户端时间不同步
江阴服务器维修培训
gale数据库宇文所安
云数据库的含义
浙江特色软件开发技术指导
香港数据中心服务器
湖南郴州市安卓软件开发待遇
数据库 图库
互联网属于科技革命吗
电脑ntp服务器
河北众科伟业网络技术有限公司
网络技术员什么级别
软件开发和数据库管理员工资
对计算机网络技术
2021年软件开发工作好找吗
国外服务器ice失败
服务器2.5寸改3.5寸
H2数据库 测试
电脑服务器应用
广州凡科互联网科技转正工资
业务驱动数据库
现在最新的网络安全手抄报
郑州软件开发定制价格表
图片服务器一般用什么
联系人备份到云服务器怎么找回来
东莞市汉方软件开发有限公司