墨墨导读:MySQL生态中服务层的二进制日志有着非常重要的作用,MVCC机制不用的binlog,是否可以去掉?本文作者详述对MySQL的binlog cache的理解。
数据技术嘉年华,十周年盛大开启,点我立即报名!大会以“自研·智能·新基建——云和数据促创新 生态融合新十年” 为主题,相邀数据英雄,总结过往十年历程与成绩,展望未来十年趋势与目标!近60场演讲,大咖云集,李飞飞、苏光牛、林晓斌、黄东旭...,快来pick你喜欢的嘉宾主题吧!
MySQL生态中服务层的二进制日志有着非常重要的作用,有人问过MVCC机制不用的binlog,是否可以去掉,答案是否。binlog用于记录用户对数据库操作的SQL语句(除了数据查询语句),但同时用于保障高可用架构中的复制方式。
本文从一个日常不太关心的参数开始,了解一下mysql的binlog cache。
crash的截图内容:
代码语言:javascript复制2020-08-01T05:44:04.068924 08:00 674
[ERROR] An error occurred during flush stage of the commit.
'binlog_error_action' is set to 'IGNORE_ERROR'.
Hence turning logging off for the whole duration of the MySQL server process.
To turn it on again: fix the cause, shutdown the MySQL server and restart it.
代码语言:javascript复制
从上述错误信息中了解到奥binlog flush无法进行下去,抛出binlog_error的异常,最终导致MySQL crash。
1)从上述错误中binlog_error_action
binlog_error_action:这个参数的意义在保证正确的写入binary log日志, ,默认值为 ABORT_SERVER,当出现错误的时候会使 MySQL 在写 binlog 遇到严重错误时直接退出( 即 Crash 动作)
当binlog_error_action设置为IGNORE_ERROR时,如果服务器遇到这样的错误,它将继续正在进行的事务,记录错误,然后停止日志记录,并继续执行更新。要恢复二进制日志记录,必须再次启用log_bin,这需要重新启动服务器。
2)从上述描述中可以推测到跟binlog写入有关。
mysql里binlog里参数有以下两个binlog_cache_size,max_binlog_cache_size,以下两个参数都是会话级别的。
binlog_cache_size: 在事务期间用于保存对二进制日志的更改的缓存的大小。二进制日志缓存分配给每个客户端服务器是否支持任何事务性存储引擎,如果服务器启用了二进制日志(——log-bin选项)。如果经常使用大型事务,可以增加缓存大小以获得更好的性能。
Binlog_cache_use和Binlog_cache_disk_use状态变量可以用于调优这个变量的大小
max_binlog_cache_size: 会话级别的参数,如果一个事务需要超过这么多字节的内存,服务器就会生成一个多语句事务,该事务需要超过’max_binlog_cache_size’字节的存储错误。最小值是4096。最大可能值为16EB (exabytes)。推荐最大值为4GB;这是因为MySQL目前无法处理大于4GB的二进制日志位置。 max_binlog_cache_size仅设置事务缓存的大小;语句缓存的上限由max_binlog_stmt_cache_size系统变量控制。
从以上理解来看 就是说binlog缓存大小无法超过4G的大小限制。
3)binlog_cache_size大小如何控制:
Binlog_cache_use:使用二进制日志缓存的事务数。 Binlog_cache_disk_use:使用临时二进制日志缓存但超过binlog_cache_size值并使用临时文件存储事务语句的事务数。 Binlog_stmt_cache_use:使用二进制日志语句缓存的非事务性语句的数量。 Binlog_stmt_cache_disk_use:使用二进制日志语句缓存但超过binlog_stmt_cache_size值并使用临时文件存储这些语句的非事务语句的数量。
4)从源码分析:
报错MYSQL_BIN_LOG::handle_binlog_flush_or_sync的时候触发的错误
分析1:无法创建io 缓存的时候出现问题Could not create IO cache 就是所谓的空间不足的情况
binlog cache 不够的时候使用tmp空间, No space left on device 即临时目录空间不足,在 同一个会话下 执行 commit 或者 再开启一个事务 就会立即触发 binlog_error_action,导致 MySQL 立即崩掉,且 errorlog 里会出现 binlog error 报错。
临时表需要设置一定的范围:
innodb_temp_data_file_path = ibtmp1:1G:autoextend:max:100G
分析2:MYSQL_BIN_LOG::ordered_commit
以下有两个阶段 flush 和sync阶段
- flush stage:通知底层存储引擎日志刷盘
- binlog fsync:落盘
这两个过程基本跟刷磁盘有关联,一般出现问题的情况是硬盘空间出现坏道,或则 刷盘过程中出现外部原因导致服务器突然crash。 如:停电
这时需要重新启动服务70%以上能自动检测恢复,如不行需要通过innodb_force_recovery进行启动,这样就比较麻烦,需要mysqldump导出,导入数据方式重新搭建。
总结
1.binlog_cache设置要合理化,默认是32k ,按照服务器资源情况,建议改成 1M~16M 2.尽量避免大事务,除非用到大事务也需要通过global status 状态进行合理设置 相关参数 3.建立监控报警体系是预防这类问题的最好方式。
数据技术嘉年华,汇聚业内多种数据库最佳实践和顶级技术专家,只为总结 2020 ,与您尽享技术前沿,领先一步卓立变革潮头!
墨天轮原文链接:https://www.modb.pro/db/33376(复制到浏览器中打开或者点击“阅读原文”)