由于业务写入了一条大业务,导致 MySQL 的 binlog 胀大。在解析大的 binlog 时,经常会遇到这个问题,导致无法解析,没有其他东西的情况下,很难分析问题。

作者:孙绪宗,新浪微博 DBA 团队工程师,首要担任 MySQL、PostgreSQL 等联络型数据库运维

爱可生开源社区出品,原创内容未经授权不得随意运用,转载请联络小编并注明来源。

本文共 3200 字,估计阅览需求 10 分钟。

故障现象

由于业务写入了一条大业务,导致 MySQL 的 binlog 胀大。在解析大的 binlog 时,经常会遇到这个问题,导致无法解析,没有其他东西的情况下,很难分析问题。

故障复现

[root@xuzong mysql]# ls -lh mysql-bin.003300
-rw-r----- 1 my3696 mysql 6.7G Oct 30 16:24 mysql-bin.003300
[root@xuzong mysql]# /usr/local/mysql-5.7.35/bin/mysqlbinlog -vv mysql-bin.003300 > 1.sql
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.334z3P' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)

猜想

  1. 可能是配置文件中 tmpdir 的问题,但是修正这个得重启 MySQL。
  2. 能不能在不重启 MySQL 的情况下,修正这个暂时空间。

验证猜想

猜想一

看一下 my.cnf 设置的 tmpdir,发现并不是运用的这个参数,看来猜想一不对。

[root@mysql mysql]# cat my.cnf | grep tmpdir
tmpdir                          = /data1/dbatemp

猜想二

网上搜了一下,大部分是讲暂时表满怎样处理的,也便是猜想一的计划,并没有很清晰的方法来修正 mybinlog 解析时,所运用的的暂时句柄占用空间。

问题分析

只能看看源码,看一下 mysqlbinlog 到底是怎样获取 tmpdir 的。

mysqbinlog.cc
int main(int argc, char** argv)
{
........
  MY_TMPDIR tmpdir;
  tmpdir.list= 0;
  if (!dirname_for_local_load)
  {
    if (init_tmpdir(&tmpdir, 0))
      exit(1);
    dirname_for_local_load= my_strdup(PSI_NOT_INSTRUMENTED,
                                      my_tmpdir(&tmpdir), MY_WME);
  }
........
}
mf_tempdir.cc
my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist)
{
  char *end, *copy;
  char buff[FN_REFLEN];
  DBUG_ENTER("init_tmpdir");
  DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL"));
  Prealloced_array<char*, 10, true> full_list(key_memory_MY_TMPDIR_full_list);
  memset(tmpdir, 0, sizeof(*tmpdir));
  if (!pathlist || !pathlist[0])
  {
    /* Get default temporary directory */
    pathlist=getenv("TMPDIR");	/* Use this if possible */ //这里能看到是获取的机器环境变量
#if defined(_WIN32)
    if (!pathlist)
      pathlist=getenv("TEMP"); //windows是temp
    if (!pathlist)
      pathlist=getenv("TMP");  //linux是tmp
#endif
    if (!pathlist || !pathlist[0])
      pathlist= DEFAULT_TMPDIR;
  }
........
}

好家伙,竟然是获取的机器环境变量,那么这个问题就处理了。

问题处理

暂时修正一下机器的 tmpdir 变量即可。

[root@mysql mysql]# export TMPDIR="/data1"
[root@mysql mysql]# echo ${TMPDIR:-/tmp}
[root@xuzong mysql]# /usr/local/mysql-5.7.35/bin/mysqlbinlog -vv mysql-bin.003300 > 1.sql

总结

  1. 有问题还是要看看源码。
  2. 可以考虑运用 binlog 解析东西,比方 bin2sql 处理问题。
  3. 可以看看慢日志里是否有记录。

弥补

原来这个问题在 MySQL 官方手册 中有所描述,在此做一个弥补。

Binlog 太大导致无法解析怎样办?

When running mysqlbinlog against a large binary log, be careful that the filesystem has enough space for the resulting files. To configure the directory that mysqlbinlog uses for temporary files, use the TMPDIR environment variable.

更多技术文章,请访问:opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至出产环境的 SQL 审阅和管理。支撑主流的开源、商业、国产数据库,为开发和运维供给流程自动化能力,提高上线功率,提高数据质量。