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内核开发与优化必备宝典) ...
随机推荐
- Python之旅.第三章.函数3.30
一.迭代器 1.什么是迭代?:迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来2.要想了解迭代器到底是什么?必须先了解一个概念,即什么是可迭代的对象?可迭代的对象:在python中,但凡内置 ...
- Linux入门:vi 和 vim
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器. 本文介绍了vi (vim)的基本使用方法,但对于普通用户来说基本上够了! 转自:http://www.l ...
- KNN算法简单应用
这里是写给小白看的,大牛路过勿喷. 1 KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集 ...
- 基于哈夫曼编码的文件压缩(c++版)
本博客由Rcchio原创 我了解到很多压缩文件的程序是基于哈夫曼编码来实现的,所以产生了自己用哈夫曼编码写一个压缩软件的想法,经过查阅资料和自己的思考,我用c++语言写出了该程序,并通过这篇文章来记录 ...
- Mysql 测试题
一. 表结构和数据 作业要求 /* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL ...
- Linux:sheel脚本for的用法,及日期参数+1day用法
记录下shell的for的用法,及参数是日期的情况下,该日期+1day的用法: #!/usr/bin/env bash source /app/catt/login.sh p_days="2 ...
- 菜鸟容易中的招__setattr__
class Counter: def __init__(self): self.counter = 0 # 这里会触发 __setattr__ 调用 def __setattr__(self, nam ...
- JQuery开发报错集锦
报错一:JQuery $.each遍历JSON字符串报Uncaught TypeError:Cannot use 'in' operator to search for "70". ...
- Vue mint ui用在消息页面上拉加载下拉刷新loadmore 标记
之前总结过一个页面存在多个下拉加载的处理方式,今天再来说一下在消息页面的上拉加载和下拉刷新,基本上每个app都会有消息页面,会遇到这个需求 需求:每次加载十条数据,上拉加载下拉刷新,并且没有点击查看过 ...
- js数据结构之栈、队列(数据结构与拉火车游戏)
1.js实现队列的数据结构(先进先出) function Queue (array) { if(Object.prototype.toString.call(array)!="[object ...