水平有限整理自己的学习笔记,如果有误请谅解。
最近老是看到有朋友报错如下:
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
虽然错误提示非常明确,但是我还是对binlog cache的使用方式进行了学习整理下来,这部分也是我一直疑惑的地方,也希望通过本文接触读者的疑惑。
本文约定:
- binlog cache:实际上就是参数binlog_cache_size指定的大小,它指定的是一段内存空间用于存储生成的binlog event,是事物级别的参数。
- binlog cache 临时文件:实际上就是参数max_binlog_cache_size指定的大小,它指定是一个临时磁盘文件存储由于binlog cache不足溢出的binlog event,其名字由"ML"打头,是事物级别的参数。
- binlog file:代表就是我们平时说的binglog 文件,由max_binlog_size指定大小。
- binlog event:代表是各种各样的binlog中的记录比如MAP_EVENT/QUERY EVENT/XID EVENT/WRITE EVENT等。
本文源码版本:
- percona 5.7.14
一、通常事物binlog event的写入流程
这里首先给出写入过程,让大家有一个大概的理解。
注意这个流程都是对于一个事物来讲的。一旦事物提交,binlog cache和binlog 临时文件都会释放掉,因为binlog已经固化到了binlog file。同时如果事物中包含多个DML语句,那么他们共享的一套的binlog cache和binlog 临时文件。
- 事物开启。
- 执行dml语句,在dml语句第一次执行的时候会分配内存空间binlog cache。
- 执行dml语句期间生成的event不断写入到binlog cache。
- 如果binlog cache的空间已经满了,则将binlog cache的数据写入到binlog临时文件,同时清空binlog cache。如果binlog临时文件的大小大于了max_binlog_cache_size的设置则抛错ERROR 1197 (HY000)。
- 事物提交,整个binlog cache和binlog临时文件数据全部写入到binlog file中进行固化,释放binlog cache和binlog临时文件。但是注意此时binlog cache的内存空间留用供下次事物使用,但是binlog临时文件被截断为0,保留文件描述符。其实也就是IO_CACHE(参考后文)保留,并且保留IO_CACHE中的分配的内存空间,和物理文件描述符。
- 断开连接,这个过程会释放IO_CACHE同时释放其持有的binlog cache内存空间以及持有的binlog 临时文件。
本文研究就是步骤3和步骤4的写入过程,和binlog cache以及binlog 临时文件的实现方式。同时本文不描述binlog_stmt_cache_size和max_binlog_stmt_cache_size的作用,因为他们和binlog_cache_size、max_binlog_cache_size参数的函数一致,只是存储是非事物语句的binlog event,但是在讨论数据结构的时候还是给出部分解释。
二、相关数据结构简介
binlog_cache_mngr类:
这个类中包含了两个cache实际上就是binlog cache和binlog stmt cache,如下:- binlog_stmt_cache_data stmt_cache;
- binlog_trx_cache_data trx_cache;
其中包含一些方法用于访问这两个cache。同时将整个binlog event写入到binlog file的方法也在其中叫做flush,栈帧如下: