mysql两阶段提交(mysql两阶段提交协议)

http://www.itjxue.com  2023-01-25 00:53  来源:未知  点击次数: 

mysql binlog 中的 为什么会有 rollback

当启动Binlog后,事务会产生Binlog Event,这些Event被看做事务数据的一部分。因此要保证事务的Binlog Event和InnoDB引擎中的数据的一致性。所以带Binlog的CrashSafe要求MySQL宕机重启后能够保证:

- 所有已经提交的事务的数据仍然存在。

- 所有没有提交的事务的数据自动回滚。

- 所有已经提交了的事务的Binlog Event也仍然存在。

- 所有没有提交事务没有记录Binlog Event。

这些要求很好理解,如果重启后数据还在,但是Binlog Event没有了,就没办法复制到其他节点上了。如果重启后,数据没了,但是Binlog Event还在,那么不存在的数据就会被复制到其他节点上,从而导致主从的不一致。

为了保证带Binlog的CrashSafe,MySQL内部使用的两阶段提交(Two Phase Commit)。

2 - MySQL的Two Phase Commit(2PC)

在开启Binlog后,MySQL内部会自动将普通事务当做一个XA事务来处理:

- 自动为每个事务分配一个唯一的ID

- COMMIT会被自动的分成Prepare和Commit两个阶段。

- Binlog会被当做事务协调者(Transaction Coordinator),Binlog Event会被当做协调者日志。

想了解2PC,可以参考文档:【。】

- 分布式事务ID(XID)

使用2PC时,MySQL会自动的为每一个事务分配一个ID,叫XID。XID是唯一的,每个事务的XID都不相同。XID会分别被Binlog和InnoDB记入日志中,供恢复时使用。MySQ内部的XID由三部分组成:

- 前缀部分

前缀部分是字符串"MySQLXid"

- Server ID部分

当前MySQL的server_id

- query_id部分

为了保证XID的的唯一性,数字部分使用了query_id。MySQL内部会自动的为每一个语句分配一个query_id,全局唯一。

参考代码:sql/xa。h的struct xid_t结构。

- 事务的协调者Binlog

Binlog在2PC中充当了事务的协调者(Transaction Coordinator)。由Binlog来通知InnoDB引擎来执行prepare,commit或者rollback的步骤。事务提交的整个过程如下:

1. 协调者准备阶段(Prepare Phase)

告诉引擎做Prepare,InnoDB更改事务状态,并将Redo Log刷入磁盘。

2. 协调者提交阶段(Commit Phase)

2.1 记录协调者日志,即Binlog日志。

2.2 告诉引擎做commit。

注意:记录Binlog是在InnoDB引擎Prepare(即Redo Log写入磁盘)之后,这点至关重要。

在MySQ的代码中将协调者叫做tc_log。在MySQL启动时,tc_log将被初始化为mysql_bin_log对象。参考sql/binlog.cc中的init_server_components():

if (opt_bin_log) tc_log= mysql_bin_log;

而在事务提交时,会依次执行:

tc_log-prepare();

tc_log-commit();

参考代码:sql/binlog.cc中的ha_commit_trans()。当mysql_bin_log是tc_log时,prepare和commit的代码在sql/binlog.cc中:

MYSQL_BIN_LOG::prepare();

MYSQL_BIN_LOG::commit();

-协调者日志Xid_log_event

作为协调者,Binlog需要将事务的XID记入日志,供恢复时使用。Xid_log_event有以下几个特点:

- 仅记录query_id

因为前缀部分不变,server_id已经记录在Event Header中,Xid_log_event中只记录query_id部分。

- 标志事务的结束

在Binlog中相当于一个事务的COMMIT语句。

一个事务在Binlog中看起来时这样的:

Query_log_event("BEGIN");DML产生的events; Xid_log_event;

- DDL没有BEGIN,也没有Xid_log_event 。

- 仅InnoDB的DML会产生Xid_log_event

因为MyISAM不支持2PC所以不能用Xid_log_event ,但会有COMMIT Event。

Query_log_event("BEGIN");DML产生的events;Query_log_event("COMMIT");

问题:Query_log_event("COMMIT")和Xid_log_event 有不同的影响吗?

- Xid_log_event 中的Xid可以帮助master实现CrashSafe。

- Slave的CrashSafe不依赖Xid_log_event

事务在Slave上重做时,会重新产生XID。所以Slave服务器的CrashSafe并不依赖于Xid_log_event 。Xid_log_event 和Query_log_event("COMMIT"),只是作为事务的结尾,告诉Slave Applier去提交这个事务。因此二者在Slave上的影响是一样的。

3 - 恢复(Recovery)

这个机制是如何保证MySQL的CrashSafe的呢,我们来分析一下。这里我们假设用户设置了以下参数来保证可靠性:

- 恢复前事务的状态

在恢复开始前事务有以下几种状态:

- InnoDB中已经提交

根据前面2PC的过程,可知Binlog中也一定记录了该事务的的Events。所以这种事务是一致的不需要处理。

- InnoDB中是prepared状态,Binlog中有该事务的Events。

需要通知InnoDB提交这些事务。

- InnoDB中是prepared状态,Binlog中没有该事务的Events。

因为Binlog还没记录,需要通知InnoDB回滚这些事务。

- Before InnoDB Prepare

事务可能还没执行完,因此InnoDB中的状态还没有prepare。根据2PC的过程,Binlog中也没有该事务的events。 需要通知InnoDB回滚这些事务。

- 恢复过程

从上面的事务状态可以看出:恢复时事务要提交还是回滚,是由Binlog来决定的。

- 事务的Xid_log_event 存在,就要提交。

- 事务的Xid_log_event 不存在,就要回滚。

恢复的过程非常简单:

- 从Binlog中读出所有的Xid_log_event

- 告诉InnoDB提交这些XID的事务

- InnoDB回滚其它的事务

如何使用mysql 两阶段提交

第阶段:Java面向象编程

1.Java基本数据类型与表达式支循环

2.StringStringBuffer使用、则表达式

3.面向象抽象封装继承态类与象象初始化收;构造函数、this关键字、参数传递程、static关键字、内部类Java垃极收机制Javadoc介绍

4.象实例化程、覆盖、final关键字、抽象类、接口、继承优点缺点剖析;象态性:类父类间转换、抽象类接口态应用、态带处

5.Java异处理异机制原理

6.用设计模式:Singleton、Template、Strategy模式

7.JavaAPI介绍:种基本数据类型包装类SystemRuntime类DateDateFomat类等

8.Java集合介绍:Collection、Set、List、ArrayList、Vector、LinkedList、Hashset、TreeSet、Map、HashMap、TreeMap、Iterator、Enumeration等用集合类API

9.Java

I/O输入输流:FileFileRandomAccess类字节流InputStreamOutputStream字符流Reader

Writer及相应实现类IO性能析字节字符转化流包装流概念及用包装类计算机编码

10.Java高级特性:反射、代理泛型

11.线程原理:何程序创建线程(Thread、Runnable)线程安全问题线程同步线程间通讯、死锁

12.Socket网络编程

第二阶段:Java

Web发

1.Java解析XML文件DOM4J

2.MySql数据库应用、表连接查询应用

3.JspServlet应用

4.Http协议解析

5.Tomcat服务器应用配置

6.WebService服务配置应用

第三阶段:android UI编程

1、Android发环境搭建:Android介绍Android发环境搭建第Android应用程序Android应用程序目录结构

2、Android初级控件使用:

TextView控件使用

Button控件使用

EditText控件使用

ImageView使用

RadioButton使用

Checkbox使用

Menu使用

3、Android高级控件使用:

Autocompletion使用

ListView使用

GridView使用

Adapter使用

Spinner使用

Gallary使用

ScrollView使用

4、框与菜单使用:

Dialog基本概念

AlertDialog使用

DatePickerDialog使用

Menu使用

自定义Menu实现

5、控件布局:

线性布局使用

相布局使用

表格布局使用

6、Acitivity管理:

AndroidManifest.xml文件作用

Intent使用

使用Intent传递数据

启Activity

IntentFilter使用

Activity Group使用

7、自定义控件实现:

自定义ListView实现

折叠ListView使用

自定义Adapter实现

自定义View实现

态控件布局实现

第四阶段:android网络编程与数据存储

1、基于Android平台HTTP通讯:

Http协议顾

Apache Commons 工具包介绍

使用Get向服务器提交数据

解析服务器响应数据

使用POST向服务器提交数据实现

向服务器提交非文本数据实现

使用Http协议实现线程载

使用Http协议实现断点续传

2、Android数据存储技术:

SQLite3数据库简介

SQL语句顾

SQLite3编程接口介绍

SQLite3事务管理

SQLite3游标使用

SQLite3性能析

访问SDCard

访问SharedPreferences

3、ContentProvider使用:ContentProvider实现共享数据、URI

解析与UriMatcher、ContentUris使用、使用ContentResolver操作ContentProvider、

ContentProvider监听Android异步操作:Handler使用;异步任务基本概念;AsyncTask使用

第五阶段:android手机硬件管理

1、图及定位技术:GPS简介;LocationManager使用;Google Map添加标记;查询某附近建筑;使用Google Map实现点点导航

2、传器使用:向、加速度(重力)、光线、磁场、距离、温度等传器使用

3、近场通信技术:NFC技术简介;NFC技术用场景介绍;NFC技术实现

4、媒体管理技术:MediaPlayer使用

5、触摸屏技术:手势识别;点触摸技术

第六阶段:Android图形编程技术

1、图形处理基础:2D图形编程基础;

2、点、线、面等基本图形元素绘制;

3、Android画框架简介;

4、位移画实现;

5、淡入淡画实现;

6、旋转画实现;

7、Matrix使用

第七阶段:Android游戏发

1、Android游戏发:Android游戏发概述;

2、SurfaceView使用;

3、物理球技术;

4、碰撞检测技术;

5、图片、文字背景音乐等资源使用;

6、游戏引擎基础概念;

7、Cocoa2d-Android引擎使用;

8、OpenGL ES使用

MySQL的Binlog与主从复制

在MySQL中,可以使用多种存储引擎。其中最常用的InnoDB引擎支持事务,Redo Log和Undo Log就是InnoDB里面的工具,用于实现事务。而Binlog是MySQL层面的东西,用于实现主从复制,与使用的存储引擎无关。

通过监听并解析Mater的Binlog,也可以实现将MySQL中的数据同步到其他应用组件中(比如更新缓存)的效果。

在不发生宕机的情况下,未提交的事务和已回滚的事务是不写入Binlog日志中的,只有提交成功的事务才写入Binlog日志。这一点和Redo Log不一样,Redo Log中会记录未提交、已回滚的事务内容。

Binlog是一种逻辑日志——例如Binlog的statement格式记录原始SQL语句、RAW格式记录某一行修改前后的值——且一个事务的日志在Binlog中是连续排列的,因此要求每个事务都要串行地写入,这意味着每个事务在写Binlog之前都要排他地锁住Binlog,这会导致写的效率很低。MySQL5.6之后,通过pipline技术异步地批量化将已提交的事务内容写入Binlog。

一个事务的提交既要写Binlog日志又要写Redo Log日志,如何保证双写的原子性?一个写成功,写另外一个时发生宕机,重启后如何处理?在讨论这个问题之前,先说下Binlog自身写入的原子性问题:Binlog刷盘到一半,出现宕机,这个问题和Redo Log的写入原子性是同样的问题,通过类似于checksum的办法或者Binlog中的结束标记来判断出某个事务的Binlog这是不是不完整的Binlog,从而把不完整的部分截掉。对于客户端来说,此时宕机,事务肯定是没有提交成功的,所以截掉也没问题。下面来讲如何保证双写Binlog和Redo Log的原子性。由于双写Binlog和Redo Log发生在同一台机器上,这其实是一个内部分布式事务,可以使用两阶段提交法来实现双写的原子性。简单来说就是:

1)第一阶段(准备阶段):MySQL Server要求innoDB完成将事务内容写入Redo Log中的工作,只等事务提交;以及,MySQL Server完成Binlog内容写入内存的工作,只等刷盘。两个都准备好之后,会向MySQL Server发送OK反馈,MySQL Server紧接着执行第二阶段。

2)第二阶段(提交阶段):收到客户端的Commit指令,MySQL Server先将内存中的Binlog刷盘,然后让innoDB执行事务的提交。两个都完成之后,会向MySQL Server发送OK反馈,两阶段提交结束。

若双写Binlog和Redo Log的过程中发生宕机,处理思路为:

1)若宕机发生在第一阶段,此时Binlog还在内存中,宕机导致全部消失。而Redo Log记录了未提交的日志,MySQL Server重启后感知到Binlog中不存在Redo Log中记录的未提交事务,会自行回滚未提交事务的Redo Log日志;

2)若宕机发生在第二阶段,Binlog写了一半,innoDB还未执行提交,MySQL Server重启后会对Binlog做截断,对Redo Log中记录的未提交事务做回滚;

3)若宕机发生在第二阶段,Binlog写入成功,innoDB还未执行提交,MySQL Server重启后会通过checksum的办法或者Binlog中的结束标记感知到Binlog写入成功,紧接着对Binlog中存在的、但Redo Log未提交的事务发起提交。

在MySQL的Master / Slave集群模式中,有三种主从复制模式:

1)同步复制:所有的Slave都收到Master发送的Binlog,并且接收完,Master才认为事务提交成功,再对客户端返回成功。这种方式最安全,但是性能很差;

2)异步复制:只要Master事务提交成功,就对客户端返回成功。后台线程异步地将Binlog发送给Slave,然后Slave回放Binlog。这种方式性能最好,但是可能会导致数据丢失;

3)半同步复制:Master事务提交后,同时把Binlog同步给Slave,只要有部分(数量可以配置)Slave收到了Binlog,就认为事务提交成功,对客户端返回。

对于半异步复制,如果Slave超时后还未返回,也会退化为异步复制。所以无论是异步复制还是半异步复制,都无法严格保证主从中的数据完全一致,主从复制的延迟会导致主节点宕机后部分数据未来得及同步到从节点,从而丢失数据。但是主节点宕机后,还是要立即切换到从节点,保证服务的可用(牺牲一致性保证可用性),数据的丢失可以通过后续的人工干预来补偿。

简介mysql之mysql语句执行流程

1.一条查询语句如何执行?

2.一条更新语句如何执行?

3.innodb的redolog是什么?

4.什么是写缓冲

5.写缓冲一定好吗?

6.什么情况会引发刷脏页

关于一条mysql查询语句在mysql中的执行流程

如select name from test where id=10;

1.连接器---先与mysql服务端连接器建立连接,若查询缓存命中则直接返回 (查询缓存的弊端:查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。)

2.分析器---词法分析告诉服务端你要干什么(我要找 test表中id为10的名字) ( 其中sql语法错误在这块暴露 )

3.优化器---服务端会思考该怎么执行最优(索引的选择)

4.执行器---检查用户对库对表的权限

5.存储引擎--存储数据,提供读写接口

以update a set name=1 where id=1;

主要区别在于在查询到数据之后(select name from a where id=1),如果是innodb引擎它会进行日志的两阶段提交:

1.开启事务,写入redolog(innodb引擎特有),并更新内存

3.写入binlog,提交事务,commit

我们知道mysql数据存储包含内存与磁盘两个部分,innodb是按数据页(通常为16k)从磁盘读取到内存中的(剩余操作在内存中执行),当要更新数据时,若目标数据的数据页刚好在内存中,则直接更新。不在呢?

将这个更新操作(也可能是插入) 缓存在change buffer中 (redolog也会记录这个change buffer操作)等到下一次查询要用到这些数据时,再执行这些操作,改变数据(称为合并操作记录称为merge)。

innodb_change_buffer_max_size

innodb_change_buffering

先介绍两个概念

因为redolog是环形日志,当redolog写满时,就需要“擦掉”开头的一部分数据来达到循环写,这里的擦掉指,指将redolog日志的checkpoint位置从 CP推进到CP‘ ,同时将两点之间的脏页刷到磁盘上(flush操作),此时系统要停止所有的更新操作(防止更新操作丢失)

1.系统内存不足。当要读取新的内存页时就要淘汰一些数据页,如果淘汰的正好是脏页,就要执行一次flush操作

2.Mysql认为系统处于“空闲状态”

3.正常关闭Mysql

上述后两者场景(系统空闲和正常关闭)对于性能都没太大影响。

当为第一种redolog写满时,系统无法执行更新操作,所有操作都会堵塞

当为第二种内存不够用时,如果淘汰脏页太多,影响mysql响应时间

后两者刷脏页会影响性能,所以Mysql需要有刷脏页控制策略,可以从以下几个设置项考虑

1.设置innodb_io_capacity告诉innodb所在主机的IO能力

(责任编辑:IT教学网)

更多

推荐新书快递文章