日志
分类
二进制日志binlog
binlog group commit技术
binlog group commit原理
数据结构
代码流程
binlog_flush_cache()
MYSQL_BIN_LOG::write_transaction_to_binlog()
MYSQL_BIN_LOG::write_transaction_to_binlog()
事务排队queue_for_group_commit()
leader 线程
trx_group_commit_leader()
二进制日志binlog
binlog group commit技术
binlog group commit原理
数据结构
代码流程
binlog_flush_cache()
MYSQL_BIN_LOG::write_transaction_to_binlog()
MYSQL_BIN_LOG::write_transaction_to_binlog()
事务排队queue_for_group_commit()
leader 线程
trx_group_commit_leader()
分类
- 错误日志:记录系统启动,运行及停止过程中出现的问题。
- 普通日志:数据库执行的所有语句以及语句开始执行的时间等 。
- 慢日志:数据库所有满查询的相关的信息。
- 二进制日志:以事件的形式记录了数据库的库表结构以及表数据的所有变更信息。
二进制日志binlog
0:作用:复制和备份
- 结构:一系列binlog文件和一个index文件。
- index:记录当前使用了哪些binlog文件
- 数据库所有的变更信息以事件的形式记录在binlog文件中。
- binlog的格式: 1.STATEMENT 2. ROW 3. MIXED。
- binlog文件:一个4字节常量作为开头,后面跟着一系列的binlog事件。
- binlog事件:公有事件头,私有事件头和事件体3个部分组成。
7.事件类型:
- FORMAT_DESCRIPTION_EVENT ,
定义为解析binlog中其他的事件,出现为第一个事件,仅出现一次。 - QUERY_EVENT
使用:1. 事务开始时,在bonlog中记录一个类型为QUERY_EVENT的BEGIN事件。
- 在STATEMENT格式的binlog中,具体执行的SQL语句保存在QUERY)EVENT事件中。
- 对于ROW格式的binlog中,所有的DDL操作以文本格式记录在QUERY_EVENT事件中。
- ROWS_EVENT
使用:
- 在STATEMENT格式的binlog中,增删改查的SQL语句保存在QUERY)EVENT事件中。
- 对于ROW格式的binlog中,对数据库的更改记录在QUERY_EVENT事件中。
- TABLE_MAP_EVENT
ROW格式的binlog文件中,每个ROWS_EVENT事件之前都有一个,用于描述表的内部id和结构定义。 - XID_EVENT
当提交事务时,表示事务的结束。在进行崩溃恢复是,根据在binlog中的提交情况来决定是否提交存储引擎种状态为presented的事务。 - BINLOG_CHECKPOINT_EVENT
用于崩溃恢复。当某个binlog文件内部的所有事务都在存储引擎内部提交,这时写入该事件;执行恢复时,根据所读取的该事件决定哪些
binlog文件不用扫描。
binlog group commit技术
- 为了持久化操作,系统通过fynsc操作。但是fsync速度有限。
- 事务提交3个步骤
- 事务在存储引擎准备好。处于准备状态的事务可以被回滚,也可以被提交。
- 事务的所有修改写入binlog中并进行持久化。这一步完成后,当数据库恢复时,存储引擎准备好但是没有提交的事务可以通过binlog恢复。
- 事务在存储引擎内部提交,这一步完成后对应的binlog对于恢复来说就没有意义了。
binlog group commit原理
- 核心思想:多个并发需要提交的事务之间共享一个fsync操作进行数据持久化。
数据结构
- bnlog_cache_mngr类
事务在提交前,他对数据库的修改不会直接写入到binlog中,而是还存在这个类中;commit之后,才写入binlog中。
位置://sql/loc.cc - group_commit_entry结构
位置://sql/log.h
一个该结构体对饮即将写入binlog的一个事务,利用队列结构实现。
代码流程
- ha_commit_trans()
负责:
*. 事务在引擎内部准备好;
*. 事务写入binlog中;
*. 在引擎内部提交该事务。 - 事务写到binlog中, 调用 log_and_order()
//sql/log.cc
int MYSQL_BIN_LOG::log_and_order(THD *thd, my_xid xid,bool all.
bool need_prepare_ordered __attribute__((unsed)),
bool need_commit_ordered __attribute__((unsed)),
// 参数:线程上下文;xid是该事务的id;all (true:表示这个事务是用户主要提交或者执行DDL被动提交)
// 最后两个没有执行。
过程:
*. 获取该事务相关的binlog_cache_mngr结构。
*.写入某个binlog文件,调用binlog_commit_flush_xid_caches()函数;
*. 将写入某个binlog文件这一信息放入返回值。
- binlog_commit_flush_xid_caches()函数
staticinlineint binlog_commit_commit_flush_xid_caches(THD *thd,
binlog_cache_mngr *cache_mngr,bool all, my_xid xid);
- xid不为空,一个xid事件作为事务的结束。
- xid为空时,我们以一个内容为COMMIT的QUERY_EVENT事件来标记该事务结束。
- 调用binlog_flush_cache() 将事务改写到binlog中。
binlog_flush_cache()
binlog_flush_cache()
功能:
- 在事务提交时,将还未写入到binlog_cache_mngr的内容全部写入到binlog_cache_mngr中
- 调用MYSQL_BIN_LOG::write_transaction_to_binlog()函数将该事务产生的所有修改写入到binlog中。
MYSQL_BIN_LOG::write_transaction_to_binlog()
过程:
*. 将事务内容封装到group_commit_entry结构中
*. 调用write_transaction_to_binlog_events函数 写入binlog中。
MYSQL_BIN_LOG::write_transaction_to_binlog()
过程:
- queue_for_group_commit函数将待提交到binlog的事务加入到组提交队列中。
- 组提交队列的第一个事务作为leader线程,调用trx_group_commit_leader()函数,负责将该组所有事务提交,然后调用
一次fsync()对binlog进行持久化,最后唤醒所有的follower线程继续往下执行。 - 如果该事务被其他的事务所在的线程加入组提交队列中。详细处理下面介绍。
事务排队queue_for_group_commit()
功能:将事务加入到组提交队列中。
// sql/log.cc
MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry * orig_entry);
- 等待其他事务提交完毕后才能提交;
- 如果该事务已被其他的等待提交的事务提交队列中,直接返回;
- 进入死循环,将事务加入组提交队列。
- 处理等待当前组提交队列的所有事物。
leader 线程
组提交队列的第一个事务作为leader线程,调用trx_group_commit_leader()函数,负责将该组所有事务提交,然后调用
一次fsync()对binlog进行持久化,最后唤醒所有的follower线程继续往下执行。
trx_group_commit_leader()
sql/log.cc
voif MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader);
- 判断binlog处于开启状态
- 将队列中的事务按顺序写入binlog中的IO_CACHE缓存中。
- 将IO_CACHE缓存内容刷新到biinlog中,并调用一次fsync操作对binlog进行持久化。
- 写完之后,对binlog文件进行检查,是否需要新建文件。
- 按照食物在binlog中的顺序调到存储引擎的commit_ordered接口,唤醒所有follower线程。
分享各种计算机技术、原理。
邮箱:ouyangcan2016@gmail.com