mysql中binlog与存储引擎的2PC
mysql内部的2PC
mysql开启binlog后实际上可以认为其数据有两份,binlog中一份,引擎中一份(这里先把存储引擎中数据看成整体的单独一份,另外也可以把binlog看成是一个引擎)。既然出现了副本,那么就不可避免的牵涉到了一致性问题,mysql在内核内部使用了经典的2PC协议实现数据一致性。
2PC协议需要一个协调者,而在binlog与引擎的2PC协议实现中,由binlog充当这一角色。
mysql事务的提交函数为ha_commit_trans
//sql/handler.cc
int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock)
{
······
}
这个函数为mysql的提交函数,这个函数在事务提交时被调用,在内部实现了2PC的事务提交。众所周知,2PC分为两个阶段,prepare与commit,而在这个函数的代码中,实际上也可以看到以这两个阶段为名的调用 tc_log->prepare(thd, all)与tc_log->commit:
int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock)
{
······
if (!trn_ctx->no_2pc(trx_scope) && (trn_ctx->rw_ha_count(trx_scope) > 1))
error= tc_log->prepare(thd, all);
······
if (error || (error= tc_log->commit(thd, all)))
{
ha_rollback_trans(thd, all);
error= 1;
goto end;
}
······
}
tc_log是一个全局指针:
//sql/tc_log.cc
TC_LOG *tc_log;
查看tc_log的定义:
/**
Transaction Coordinator Log.
A base abstract class for three different implementations of the
transaction coordinator.
The server uses the transaction coordinator to order transactions
correctly and there are three different implementations: one using
an in-memory structure, one dummy that does not do anything, and one
using the binary log for transaction coordination.
*/
class TC_LOG
{
public:
/**
Perform heuristic recovery, if --tc-heuristic-recover was used.
@note no matter whether heuristic recovery was successful or not
mysqld must exit. So, return value is the same in both cases.
@retval false no heuristic recovery was requested
@retval true heuristic recovery was performed
*/
bool using_heuristic_recover();
TC_LOG() {}
virtual ~TC_LOG() {}
enum enum_result {
RESULT_SUCCESS,
RESULT_ABORTED,
RESULT_INCONSISTENT
};
/**
Initialize and open the coordinator log.
Do recovery if necessary. Called during server startup.
@param opt_name Name of logfile.
@retval 0 sucess
@retval 1 failed
*/
virtual int open(const char *opt_name)=0;
/**
Close the transaction coordinator log and free any resources.
Called during server shutdown.
*/
virtual void close()=0;
/**
Log a commit record of the transaction to the transaction
coordinator log.
When the function returns, the transaction commit is properly
logged to the transaction coordinator log and can be committed in
the storage engines.
@param thd Session to log transaction for.
@param all @c True if this is a "real" commit, @c false if it is a "statement" commit.
@return Error code on failure, zero on success.
*/
virtual enum_result commit(THD *thd, bool all) = 0;
/**
Log a rollback record of the transaction to the transaction
coordinator log.
When the function returns, the transaction have been aborted in
the transaction coordinator log.
@param thd Session to log transaction record for.
@param all @c true if an explicit commit or an implicit commit
for a statement, @c false if an internal commit of the statement.
@return Error code on failure, zero on success.
*/
virtual int rollback(THD *thd, bool all) = 0;
/**
Log a prepare record of the transaction to the storage engines.
@param thd Session to log transaction record for.
@param all @c true if an explicit commit or an implicit commit
for a statement, @c false if an internal commit of the statement.
@return Error code on failure, zero on success.
*/
virtual int prepare(THD *thd, bool all) = 0;
};
从源码和注释中可以看出,这是一个虚基类,作为事务提交的协调器,实现了事务的prepare、commit、rollback等接口。那么既然是一个虚基类,那么实际上tc_log指针在ha_commit_trans中应该是指向继承TC_LOG类的一个子类的对象。查看这个指针在何处初始化可以发现在init_server_components中,该指针被赋值:
//sql/mysqld.cc
static int init_server_components()
{
······
if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log))
{
if (opt_bin_log)
tc_log= &mysql_bin_log;
else
tc_log= &tc_log_mmap;
}
······
}
从代码中可以看出当有超过一个支持2PC的存储引擎或者只有一个但是开启了binlog的话,tc_log就会被设置,如果开启了binlog就会以binlog作为事务的协调器。因此,ha_commit_trans中调用的实际上就是MYSQL_BIN_LOG中实现的prepare与commit.查看MYSQL_BIN_LOG中实现的prepare:
int MYSQL_BIN_LOG::prepare(THD *thd, bool all)
{
DBUG_ENTER("MYSQL_BIN_LOG::prepare");
DBUG_ASSERT(opt_bin_log);
/*
The applier thread explicitly overrides the value of sql_log_bin
with the value of log_slave_updates.
*/
DBUG_ASSERT(thd->slave_thread ?
opt_log_slave_updates : thd->variables.sql_log_bin);
/*
Set HA_IGNORE_DURABILITY to not flush the prepared record of the
transaction to the log of storage engine (for example, InnoDB
redo log) during the prepare phase. So that we can flush prepared
records of transactions to the log of storage engine in a group
right before flushing them to binary log during binlog group
commit flush stage. Reset to HA_REGULAR_DURABILITY at the
beginning of parsing next command.
*/
thd->durability_property= HA_IGNORE_DURABILITY;
int error= ha_prepare_low(thd, all);
DBUG_RETURN(error);
}
可以看出,这个函数实际上就只是调用了存储引擎接口的ha_prepare_low接口,使得引擎处于prepare状态。对于binlog而言,实际上只需要写入文件即可,因此可以认为本身就处于prepare状态。事务处于prepare状态后,调用MYSQL_BIN_LOG的commit函数进行提交。
TC_LOG::enum_result MYSQL_BIN_LOG::commit(THD *thd, bool all)
{
······
if (ordered_commit(thd, all, skip_commit))
DBUG_RETURN(RESULT_INCONSISTENT);
······
}
这个函数比较长,先省略其他部分,只看进行的提交的调用,实际上提交操作是在ordered_commit中实现。ordered_commit入口是mysql组提交的入口,暂时不深入,在这个函数中会将binlog写入,并且调用ha_commit_low在引擎进行提交。
将几个主要的函数调用栈总结如下:
ha_commit_trans
|
|_ _ _ _ MYSQL_BIN_LOG::prepare
| |
| |_ _ _ _ ha_prepare_low
|
|_ _ _ _ MYSQL_BIN_LOG::commit
|
| _ _ _ _MYSQL_BIN_LOG::ordered_commit
|
|_ _ _ _ha_commit_low
mysql中binlog与存储引擎的2PC的更多相关文章
- java面试一日一题:mysql中常用的存储引擎有哪些?
问题:请讲下mysql中常用的引擎有哪些? 分析:该问题主要考察对mysql存储引擎的理解,及区别是什么? 回答要点: 主要从以下几点去考虑, 1.mysql的存储引擎的基本概念? 2.mysql中常 ...
- mysql中四种存储引擎的区别和选择
前言 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引擎,还可以 ...
- mysql中常见的存储引擎和索引类型
存储引擎 1. 定义 存储引擎说白了就是如何存储数据.如何为存储的数据建立索引和如何更新.查询数据等技术的实现方法.因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类 ...
- 【3.3】mysql中的Federated存储引擎,远程表,相当于sql server的linked server
MySQL中针对不同的功能需求提供了不同的存储引擎.所谓的存储引擎也就是MySQL下特定接口的具体实现. FEDERATED是其中一个专门针对远程数据库的实现.一般情况下在本地数据库中建表会在数据库目 ...
- MySql中启用InnoDB数据引擎的方法
1.存储引擎是什么? Mysql中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术, ...
- [转帖]一文看懂mysql数据库本质及存储引擎innodb+myisam
一文看懂mysql数据库本质及存储引擎innodb+myisam https://www.toutiao.com/i6740201316745740807/ 原创 波波说运维 2019-09-29 0 ...
- MySQL存储引擎的实际应用以及对MySQL数据库中各主要存储引擎的独特特点的描述
MySQL存储引擎的实际应用以及对MySQL数据库中各主要存储引擎的独特特点的描述: 1.MySQL有多种存储引擎: MyISAM.InnoDB.MERGE.MEMORY(HEAP).BDB(Berk ...
- 【MySQL】MySQL(四)存储引擎、索引、锁、集群
MySQL存储引擎 MySQL体系结构 体系结构的概念 任何一套系统当中,每个部件都能起到一定的作用! MySQL的体系结构 体系结构详解 客户端连接 支持接口:支持的客户端连接,例如C.Java.P ...
- MySQL内核:InnoDB存储引擎 卷1
MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...
随机推荐
- 自己写编程语言-m语言
一直对技术有很强的兴趣,终于,决定要写自己的语言(m语言).那就先从最简单的开始:解释执行器. 一套完整的语言包含的肯定不止解释执行器了,还要有编译器和IDE,也就还要有语法高亮.智能提示等,不过还没 ...
- 面试必问---HashMap原理分析
一.HashMap的原理 众所周知,HashMap是用来存储Key-Value键值对的一种集合,这个键值对也叫做Entry,而每个Entry都是存储在数组当中,因此这个数组就是HashMap的主干.H ...
- 03-移动端开发教程-CSS3新特性(下)
1. CSS3动画 1.1 过渡的缺点 transition的优点在于简单易用,但是它有几个很大的局限. transition需要事件触发,所以没法在网页加载时自动发生. transition是一次性 ...
- IdentityServer4实战 - 基于角色的权限控制及Claim详解
一.前言 大家好,许久没有更新博客了,最近从重庆来到了成都,换了个工作环境,前面都比较忙没有什么时间,这次趁着清明假期有时间,又可以分享一些知识给大家.在QQ群里有许多人都问过IdentityServ ...
- python 鸭子类型
首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型. 在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不 ...
- idea的spring boot项目,运行时不要显示在dashboard中
将对应项目的上图配置,取消勾选即可.
- 关于 Integer 值比较的问题
今天刚好遇到这样的问题,别的不说,先上代码 public class TestInteger { public static void main(final String[] args) { fina ...
- 关于block的循环引用的问题
在block的循环引用的问题上我们都知道如果在block内部修改外部的变量的时候,要加__block以防止循环引用的问题,但是如果block是当前对象的一个属性的时候,要修改当前对象的一个属性的时候就 ...
- 服务器批量管理软件ansible安装以及配置
1.yum安装(管理主机以及被管理主机都需要安装) yum install epel-release yum install ansible 2.配置管理主机 vim /etc/ansible/hos ...
- vi和vim编辑器
VI vi是一种计算机文本编辑器,由美国计算机科学家比尔·乔伊(Bill Joy)完成编写,并于1976年以BSD协议授权发布. VIM Vim是从vi发展出来的一个文本编辑器.其代码补完.编译及错误 ...