MYSQL 什么时候同步binlog文件以及它的临时文件在哪里?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 原创:转载请注明出处 本文参考5.7官方文档以及对MYSQL进行trace和GDB,使用自制binlog解析工具 infobin 获取可以通过百度云盘 http://pan.

原创:转载请注明出处
本文参考5.7官方文档以及对MYSQL进行trace和GDB,使用自制binlog解析工具
infobin 获取可以通过百度云盘
http://pan.baidu.com/s/1jHIWUN0
帮助:
http://blog.itpub.net/7728585/viewspace-2133534/

使用引擎innodb以及mysql 5.7.13

1、什么时候生成event以及何时同步到真正的binlog文件?
我们知道在语句执行期间binlog会记录到binlog_cache_size,但是超过binlog_cache_size的会
放到临时文件,等到commit的时候写到binlog文件中,当然是考虑sync_binlog = 1的情况下
关于这段在文档中也有描述:
   Within an uncommitted transaction, all updates (UPDATE, DELETE, or INSERT) that change transactional
tables such as InnoDBtables are cached until a COMMITstatement is received by the server. At that point,
mysqldwrites the entire transaction to the binary log before the COMMIT is executed.
   When a thread that handles the transaction starts, it allocates a buffer of binlog_cache_sizeto buffer
statements. If a statement is bigger than this, the thread opens a temporary file to store the transaction.
The temporary file is deleted when the thread ends.
实际上我们可以观察2个值如下:
| Binlog_stmt_cache_disk_use | 0           |
| Binlog_stmt_cache_use        | 1           |
来观察。
其实语句执行期间binlog event会写入到buffer或者temfile中,commit的时候同步到binlog真正的文件中

2、临时文件在哪里?
在文档中只是描述了大于binlog_cache_size 会使用临时文件,那么这个临时文件放到哪里呢?
其实他是一个临时文件LINUX下使用mkstemp() API建立的,放到了参数tmpdir下面,但是因为是临时
文件ls是看不到的,但是lsof能看到,而且它占用空间,随着线程的结束而释放类似如下:
 lsof|grep delete 
名字应该是ML开头类似如下名字
/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLGWFO0T (deleted)
我的tempdir目录是/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/

官方文档也有描述:
When a thread that handles the transaction starts, it allocates a buffer of binlog_cache_size to buffer
statements. If a statement is bigger than this, the thread opens a temporary file to store the transaction.
The temporary file is deleted when the thread ends.

3、建立过程
函数 real_open_cached_file是总的接口
T@3: | | | | | | | | | >real_open_cached_file                  
T@3: | | | | | | | | | | >create_temp_file             ---建立临时文件
T@3: | | | | | | | | | | | enter: dir: /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1, prefix: ML
T@3: | | | | | | | | | | | >convert_dirname
T@3: | | | | | | | | | | | my_register_filename
T@3: | | | | | | | | | | | | >my_raw_malloc
T@3: | | | | | | | | | | | | | my: size: 111  my_flags: 16
T@3: | | | | | | | | | | | | | exit: ptr: 0x7fffd0bc0f70
T@3: | | | | | | | | | | | | <my_raw_malloc 219="" t@3:="" |="" exit:="" fd:="" 65="" <my_register_filename="" 204="" my_realpath="" info:="" executing="" realpath T@3: | | | | | | | | | | my_delete                   ---删除临时文件保留文件描述符供使用
T@3: | | | | | | | | | | | my: name /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLjBqtsQ MyFlags 16
T@3: | | | | | | | | | | <my_delete 41="" t@3:="" |="" <real_open_cached_file="" 85="" delete过后这个文件在tmp目录下就ls看不到了="" 我使用gdb打了断点,在执行my_delete这个文件是可见的, [root@testmy mysqld.1]# ls -lrt
total 0
-rw------- 1 root root 0 Feb 15 07:44 MLjBqtsQ
但是my_delete后就看不到了但是lsof看得到
[root@testmy mysqld.1]# lsof|grep MLjBqtsQ
mysqld    3267      root   66u      REG                8,3         0    6700113 /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLjBqtsQ (deleted)

标记为MLjBqtsQ (deleted) : ML为固定 jBqtsQ为随机

4、临时文件怎么使用
---在语句执行期间当然是将event不断的写入到临时文件
---当commit通过总的接口进行临时文件的到binlogfile的拷贝
   MYSQL_BIN_LOG::write_cache(THD *, binlog_cache_data *, bool)
   其中
   1、首先将binlog_cache_size中全部的数据刷新到tempfile中如下:
T@4: | | | | | | | | | | | | >reinit_io_cache
T@4: | | | | | | | | | | | | | enter: cache: 0x7fffd0c79b70 type: 1  seek_offset: 0  clear_cache: 0
T@4: | | | | | | | | | | | | | >my_b_flush_io_cache
T@4: | | | | | | | | | | | | | | enter: cache: 0x7fffd0c79b70
T@4: | | | | | | | | | | | | | | >my_write
T@4: | | | | | | | | | | | | | | | my: fd: 60  Buffer: 0x7fffd0fb6720  Count: 3395  MyFlags: 20
T@4: | | | | | | | | | | | | | | <my_write 115="" t@4:="" |="" <my_b_flush_io_cache="" 1583="" <reinit_io_cache="" 387=""  =""  这里的fd:60就是我的临时文件的文件描述符=""  2、接下来进行一个event一个event的从temp到binlog进行copy,copy的时候需要一个buffer="" 这个buffer的大小应该是event的大小 T@4: | | | | | | | | | | | | >my_read
T@4: | | | | | | | | | | | | | my: fd: 60  Buffer: 0x7fffd0fb6720  Count: 8192  MyFlags: 16
T@4: | | | | | | | | | | | | Binlog_event_writer::write_event_part
T@4: | | | | | | | | | | | | Binlog_event_writer::write_event_part
T@4: | | | | | | | | | | | | Binlog_event_writer::write_event_part
T@4: | | | | | | | | | | | | | >my_b_flush_io_cache
T@4: | | | | | | | | | | | | | | enter: cache: 0x2dfd5c8
T@4: | | | | | | | | | | | | | | >my_write
T@4: | | | | | | | | | | | | | | | my: fd: 36  Buffer: 0x33b8e50  Count: 8192  MyFlags: 52
T@4: | | | | | | | | | | | | | | <my_write 115="" t@4:="" |="" <my_b_flush_io_cache="" 1583="" <binlog_event_writer::write_event_part="" 1033="" 画一张图:=""

5、通过gdb和工具infobin进行验证(使用mysqlbinlog也可以但是不太好观察)
这里将展示一个大的DML语句然后观察一条一条event的写入:
mysql> show variables like '%binlog_cache_size%';
+-----------------------+----------------------+
| Variable_name         | Value                |
+-----------------------+----------------------+
| binlog_cache_size     | 4096                 |

mysql> select count(*) from test;
+----------+
| count(*) |
+----------+
|    24576 |
+----------+

gdb 断点打到 MYSQL_BIN_LOG::write_cache上
(gdb) b MYSQL_BIN_LOG::write_cache
Breakpoint 5 at 0x1853f2c: file /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc, line 7682.

mysql> delete from test;

断点触发,然后再打一个断点到
Breakpoint 5, MYSQL_BIN_LOG::write_cache (this=0x2dfd280, thd=0x7fffe8016730, cache_data=0x7fffe812d938, writer=0x7fffec12c810)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:7682
7682      DBUG_ENTER("MYSQL_BIN_LOG::write_cache(THD *, binlog_cache_data *, bool)");
(gdb) b my_write
Breakpoint 6 at 0x18e51c0: file /root/mysql5.7.14/percona-server-5.7.14-7/mysys/my_write.c, line 43.

多进行几次c继续发现binlog记录如下:
------>Delete Event:Pos:340(0X154) N_pos:8552(0X2168) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第一个event)
------>Delete Event:Pos:8552(0X2168) N_pos:16764(0X417c) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第二个event)
analyze_binlog:fread ERROR main.c 436 
a_binlog analyze_binlog error main.c 596 
ERROR:a_binlog fun error
报错是因为binlog没有正确结束,这肯定的。
然后再次c
------>Delete Event:Pos:340(0X154) N_pos:8552(0X2168) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第一个event)
------>Delete Event:Pos:8552(0X2168) N_pos:16764(0X417c) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第二个event)
------>Delete Event:Pos:16764(0X417c) N_pos:24976(0X6190) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第三个event)
analyze_binlog:fread ERROR main.c 436 
a_binlog analyze_binlog error main.c 596 
ERROR:a_binlog fun error

再次c
------>Delete Event:Pos:340(0X154) N_pos:8552(0X2168) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第一个event)
------>Delete Event:Pos:8552(0X2168) N_pos:16764(0X417c) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第二个event)
------>Delete Event:Pos:16764(0X417c) N_pos:24976(0X6190) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第三个event)
------>Delete Event:Pos:24976(0X6190) N_pos:33188(0X81a4) Time:1487120852 Event_size:8212(bytes) 
Dml on table: test.test  table_id:108 Gno:0 (第四个event)
analyze_binlog:fread ERROR main.c 436 
a_binlog analyze_binlog error main.c 596 
ERROR:a_binlog fun error

如此我们证明上面的说法,如此反复可以看到一个event一个event的不断从tempfile写入到binlog

6、源码接口展示
建立临时文件:

点击(此处)折叠或打开

  1. File create_temp_file(char *to, const char *dir, const char *prefix,
  2.          int mode, myf MyFlags)
  3. {
  4.   File file= -1;
  5. #ifdef _WIN32
  6.   TCHAR path_buf[MAX_PATH-14];
  7. #endif

  8.   DBUG_ENTER("create_temp_file");
  9.   DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
  10. #if defined(_WIN32)

  11.    /*
  12.      Use GetTempPath to determine path for temporary files.
  13.      This is because the documentation for GetTempFileName
  14.      has the following to say about this parameter:
  15.      "If this parameter is NULL, the function fails."
  16.    */
  17.    if (!dir)
  18.    {
  19.      if(GetTempPath(sizeof(path_buf), path_buf) > 0)
  20.        dir = path_buf;
  21.    }
  22.    /*
  23.      Use GetTempFileName to generate a unique filename, create
  24.      the file and release it's handle
  25.       - uses up to the first three letters from prefix
  26.    */
  27.   if (GetTempFileName(dir, prefix, 0, to) == 0)
  28.     DBUG_RETURN(-1);

  29.   DBUG_PRINT("info", ("name: %s", to));

  30.   /*
  31.     Open the file without the "open only if file doesn't already exist"
  32.     since the file has already been created by GetTempFileName
  33.   */
  34.   if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0)
  35.   {
  36.     /* Open failed, remove the file created by GetTempFileName */
  37.     int tmp= my_errno();
  38.     (void) my_delete(to, MYF(0));
  39.     set_my_errno(tmp);
  40.   }

  41. #else /* mkstemp() is available on all non-Windows supported platforms. */
  42.   {
  43.     char prefix_buff[30];
  44.     uint pfx_len;
  45.     File org_file;

  46.     pfx_len= (uint) (my_stpcpy(my_stpnmov(prefix_buff,
  47.                  prefix ? prefix : "tmp.",
  48.                  sizeof(prefix_buff)-7),"XXXXXX") -
  49.          prefix_buff);
  50.     if (!dir && ! (dir =getenv("TMPDIR")))
  51.       dir= DEFAULT_TMPDIR;
  52.     if (strlen(dir)+ pfx_len > FN_REFLEN-2)
  53.     {
  54.       errno=ENAMETOOLONG;
  55.       set_my_errno(ENAMETOOLONG);
  56.       DBUG_RETURN(file);
  57.     }
  58.     my_stpcpy(convert_dirname(to,dir,NullS),prefix_buff);
  59.     org_file=mkstemp(to);
  60.     if (mode & O_TEMPORARY)
  61.       (void) my_delete(to, MYF(MY_WME));
  62.     file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
  63.              EE_CANTCREATEFILE, MyFlags);
  64.     /* If we didn't manage to register the name, remove the temp file */
  65.     if (org_file >= 0 && file < 0)
  66.     {
  67.       int tmp=my_errno();
  68.       close(org_file);
  69.       (void) my_delete(to, MYF(MY_WME));
  70.       set_my_errno(tmp);
  71.     }
  72.   }
  73. #endif
  74.   if (file >= 0)
  75.   {
  76.     mysql_mutex_lock(&THR_LOCK_open);
  77.     my_tmp_file_created++;
  78.     mysql_mutex_unlock(&THR_LOCK_open);
  79.   }
  80.   DBUG_RETURN(file);
  81. }
删除临时文件,保留文件描述符供使用

点击(此处)折叠或打开

  1. int my_delete(const char *name, myf MyFlags)
  2. {
  3.   int err;
  4.   DBUG_ENTER("my_delete");
  5.   DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags));

  6.   if ((err = unlink(name)) == -1)
  7.   {
  8.     set_my_errno(errno);
  9.     if (MyFlags & (MY_FAE+MY_WME))
  10.     {
  11.       char errbuf[MYSYS_STRERROR_SIZE];
  12.       my_error(EE_DELETE, MYF(0),
  13.                name, errno, my_strerror(errbuf, sizeof(errbuf), errno));
  14.     }
  15.   }
  16.   else if ((MyFlags & MY_SYNC_DIR) &&
  17.            my_sync_dir_by_file(name, MyFlags))
  18.     err= -1;
  19.   DBUG_RETURN(err);
  20. } /* my_delete */
作者微信:

               


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
244 0
|
12天前
|
存储 SQL 关系型数据库
mysql 的ReLog和BinLog区别
MySQL中的重做日志和二进制日志是确保数据库稳定性和可靠性的关键组件。重做日志主要用于事务的持久性和原子性,通过记录数据页的物理修改信息来恢复未提交的事务;而二进制日志记录SQL语句的逻辑变化,支持数据复制、恢复和审计。两者在写入时机、存储方式及配置参数等方面存在显著差异。
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
135 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
9天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
11天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
10天前
|
安全 关系型数据库 MySQL
解决MySQL删除/var/lib/mysql下的所有文件后无法启动的问题
删除 `/var/lib/mysql` 下的所有文件后,需要重新初始化数据目录,确保正确的权限设置,并重新启动 MySQL 服务。通过按照上述步骤操作,可以解决 MySQL 无法启动的问题,并恢复数据库的正常运行。初始化数据目录后,别忘了配置安全设置,并根据需要恢复备份数据。这些步骤不仅能够恢复 MySQL 的正常运行,还能确保数据库的安全性和完整性。
25 2
|
13天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
26天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的参数文件
MySQL启动时会读取配置文件my.cnf来确定数据库文件位置及初始化参数。该文件分为Server和Client两部分,包含动态与静态参数。动态参数可在运行中通过命令修改,而静态参数需修改my.cnf并重启服务生效。文中还提供了相关代码示例和视频教程。
|
26天前
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的全量日志文件
MySQL全量日志记录所有操作的SQL语句,默认禁用。启用后,可通过`show variables like %general_log%检查状态,使用`set global general_log=ON`临时开启,执行查询并查看日志文件以追踪SQL执行详情。
|
29天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。