什么?MySQL 8.0 会同时修改两个ib_logfilesN 文件?

问题现象描述

测试MySQL单机时,无意发现,MySQL 8.0的 ib_logfilesN的显示如下:

ll ib_logfile*
-rw-r----- 1 greatsql greatsql 134217728 8月 4 18:36 ib_logfile0
-rw-r----- 1 greatsql greatsql 134217728 7月 27 17:31 ib_logfile1
-rw-r----- 1 greatsql greatsql 134217728 8月 4 18:03 ib_logfile2
-rw-r----- 1 greatsql greatsql 134217728 8月 4 18:36 ib_logfile3

其中ib_logfile0、iblogfile3的 最近改动时间为:2022-08-04 18:36

印象中,MySQL 8.0对 redo 做了大量优化,难道刷盘也做了改变?

重现现象

赶紧登录到MySQL 重新执行一条insert,再观察一下。

1  ib_logfile*
2-rw-r----- 1 greatsql greatsql 134217728 8月 9 22:55 ib_logfile0
3-rw-r----- 1 greatsql greatsql 134217728 7月 27 17:31 ib_logfile1
4-rw-r----- 1 greatsql greatsql 134217728 8月 4 18:03 ib_logfile2
5-rw-r----- 1 greatsql greatsql 134217728 8月 9 22:55 ib_logfile3
6[#3#root@greatsql82 /data/mysql8023/data 22:55:45]3 stat ib_logfile0
7 文件:"ib_logfile0"`
8 大小:134217728 块:262144 IO 块:4096 普通文件
9 设备:fd00h/64768d Inode:75740704 硬链接:1
10 权限:(0640/-rw-r-----) Uid:( 1000/ greatsql) Gid:( 1000/ greatsql)
11 最近访问:2022-08-0419:22:32.746184752+0800
12 最近更改:2022-08-0922:55:40.166964294+0800
13 最近改动:2022-08-0922:55:40.166964294+0800
14 创建时间:-`
15[#4#root@greatsql82 /data/mysql8023/data 22:56:13]4 stat ib_logfile3
16 文件:"ib_logfile3"
17 大小:134217728 块:262144 IO 块:4096 普通文件
18 设备:******* Inode:75740707 硬链接:1
19 权限:(0640/-rw-r-----) Uid:( 1000/ greatsql) Gid:( 1000/ greatsql)
20 最近访问:2022-08-0419:22:48.510210526+0800
21 最近更改:2022-08-0922:55:39.741963331+0800
22 最近改动:2022-08-0922:55:39.741963331+0800
23 创建时间:-

在MySQL端执行一个事务后,可以看到ib_logfile0、iblogfile3​都发生了改变,iblogfile3​先改变,iblogfile0后改变,且改动时间相差不到0.42s

赶紧翻一下官网手册

By default, the redo log is physically represented on disk by two files named ib_logfile0 and ib_logfile1. MySQL writes to the redo log files in a circular fashion.

没有新变化,依旧是循环写 (那为啥写了iblogfile3后,还会写iblogfile0呢?)

实践追踪

最直接的当然是去看源码,一切尽在源码中。不过看代码实在太麻烦,不太适合大多数的人,gdb debug 过程,技术要求门槛较高。

有没有一个工具,能让运维人员直观地观测一下呢?

当然有!

sysdig这是笔者在GreatSQL社区了解到的一款观测性神器。

在MySQL执行

insert into test.t values(1,’aa’);

追踪如下:

1 sysdig    proc.pid=2617and  fd.type=file  
227398301:02:18.5343362111 mysqld (2617.3021)< open fd=39(<f>/data/mysql8023/data/test/t.ibd) name=./test/t.ibd(/data/mysql8023/data/test/t.ibd) flags=1(O_RDONLY) mode=0 dev=FD00
3 `273988 01:02:18.5343819101 mysqld (2617.3021)> lseek fd=39(<f>/data/mysql8023/data/test/t.ibd) offset=0 whence=1(SEEK_CUR)
4 `273989 01:02:18.5343842661 mysqld (2617.3021)< lseek res=0
5 `273990 01:02:18.5343857781 mysqld (2617.3021)> lseek fd=39(<f>/data/mysql8023/data/test/t.ibd) offset=0 whence=2(SEEK_END)
6 `273991 01:02:18.5343866571 mysqld (2617.3021)< lseek res=114688
7 `273992 01:02:18.5343876861 mysqld (2617.3021)> lseek fd=39(<f>/data/mysql8023/data/test/t.ibd) offset=0 whence=0(SEEK_SET)
8 `273993 01:02:18.5343886751 mysqld (2617.3021)< lseek res=0
927399601:02:18.5344288311 mysqld (2617.3021)> pread fd=39(<f>/data/mysql8023/data/test/t.ibd) size=1024 pos=0
1027399701:02:18.5344464761 mysqld (2617.3021)< pread res=1024 data=:.........8..........eKq.............................@..@!......................
1127399801:02:18.5344496031 mysqld (2617.3021)> pread fd=39(<f>/data/mysql8023/data/test/t.ibd) size=16384 pos=0
1227399901:02:18.5344812721 mysqld (2617.3021)< pread res=16384 data=:.........8..........eKq.............................@..@!......................
1327400001:02:18.5344850061 mysqld (2617.3021)> close fd=39(<f>/data/mysql8023/data/test/t.ibd)
1427400101:02:18.5344873331 mysqld (2617.3021)< close res=0
1527400301:02:18.5345049901 mysqld (2617.3021)< open fd=39(<f>/data/mysql8023/data/test/t.ibd) name=./test/t.ibd(/data/mysql8023/data/test/t.ibd) flags=3(O_RDWR) mode=0 dev=FD00
1627400401:02:18.5345079221 mysqld (2617.3021)> fcntl fd=39(<f>/data/mysql8023/data/test/t.ibd) cmd=5(F_SETFL)
1727400501:02:18.5345103491 mysqld (2617.3021)< fcntl res=0(<f>/dev/null)
1827400601:02:18.5345118421 mysqld (2617.3021)> fcntl fd=39(<f>/data/mysql8023/data/test/t.ibd) cmd=8(F_SETLK)
1927400701:02:18.5345186201 mysqld (2617.3021)< fcntl res=0(<f>/dev/null)
2027401201:02:18.5345373701 mysqld (2617.3021)> pread fd=39(<f>/data/mysql8023/data/test/t.ibd) size=16384 pos=65536
2127454901:02:18.5510045512 mysqld (2617.3021)< pread res=16384 data=x...................?..KE................x......................................
2227455301:02:18.5510864132 mysqld (2617.3021)> pread fd=39(<f>/data/mysql8023/data/test/t.ibd) size=16384 pos=16384
2327457801:02:18.5531585862 mysqld (2617.3021)< pread res=16384 data=..Nv.................e>8........................................................
2427490401:02:18.5671116573 mysqld (2617.2665)> pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=1024 pos=133301760
2527490801:02:18.5671522313 mysqld (2617.2665)< pwrite res=1024 data=.......N.."......Z/........Q.......Q.......:......Z/r.........Z/...........*....26 274912 01:02:18.567167495 3 mysqld (2617.2665) > pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=13330278427 274913 01:02:18.567170922 3 mysqld (2617.2665) < pwrite res=512 data=.....x.x..".....................................................................
2827514901:02:18.5733202622 mysqld (2617.3021)> write fd=36(<f>/data/mysql8023/log/mysql-bin.000011) size=275
2927515001:02:18.5733539212 mysqld (2617.3021)< write res=275 data=...b!....K.............'.5...Q..'w{...........................9 ........8.....b.
3027524401:02:18.5742238313 mysqld (2617.2665)> pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=133302784
3127524501:02:18.5742493403 mysqld (2617.2665)< pwrite res=512 data=.....p.x..".....................................................................32 276355 01:02:18.652355052 1 mysqld (2617.2665) > pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=13330278433 276362 01:02:18.652389109 1 mysqld (2617.2665) < pwrite res=512 data=.......x..".....................................................................
3427636601:02:18.6524001271 mysqld (2617.2665)> pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=133303296
3527636901:02:18.6524046981 mysqld (2617.2665)< pwrite res=512 data=..........".......8.............................................................36 277222 01:02:18.658160528 1 mysqld (2617.2665) > pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=13330329637 277223 01:02:18.658196012 1 mysqld (2617.2665) < pwrite res=512 data=..........".......8....>$.......................................................
3827942501:02:18.7698089471 mysqld (2617.2665)> pwrite fd=11(<f>/data/mysql8023/data/ib_logfile3) size=512 pos=133303296`
3927942601:02:18.7698617081 mysqld (2617.2665)< pwrite res=512 data=.....(....".......8....>$........>$.............................................40 281529 01:02:18.924391804 3 mysqld (2617.2657) > pwrite fd=12(<f>/data/mysql8023/data/#ib_16384_0.dblwr) size=147456 pos=262144` 41 281539 01:02:18.925125943 3 mysqld (2617.2657) < pwrite res=147456 data=.E..................?..(........................................................42 302247 01:02:19.924998103 0 mysqld (2617.2661) > pwrite fd=4(<f>/data/mysql8023/data/ib_logfile0) size=512 pos=512` 43 302248 01:02:19.925043052 0 mysqld (2617.2661) < pwrite res=512 data=......".....?..(.......(........................................................

分析过程

分析以上追踪日志,可以得到:

1.(2617.3021) 2617​ 是 mysqld 进程号, 3021​ 是执行SQL语句的THREAD_OS_ID​,可以看到操作t.ibd文件(FD39)的完整过程,这里没有追踪到FD39 write的过程,说明redo日志落盘,checkpoint向前更新,就能完成事务提交,不需要等待数据的真正落盘。

2.

  • 2665线程 thread/innodb/log_writer_thread 先写/data/mysql8023/data/ib_logfile3
  • 2661线程thread/innodb/log_checkpointer_thread 更新/data/mysql8023/data/ib_logfile0 pos512 和 pos1536 两个位置
select*from  threads  where  THREAD_OS_ID  in(2665,2661) \G
***************************1. row ***************************
THREAD_ID:27
NAME: thread/innodb/log_checkpointer_thread
TYPE: BACKGROUND

...

THREAD_OS_ID:2661
RESOURCE_GROUP: SYS_default
***************************2. row ***************************
THREAD_ID:31
NAME: thread/innodb/log_writer_thread
TYPE: BACKGROUND
...
THREAD_OS_ID:2665
RESOURCE_GROUP: SYS_default
2 rows inset(0.00 sec)

3.log_filesN每次更新的大小为512B *N N>=1

4.当前正在记录redo内容的文件为ib_logfile3 pos到了133303296

以上通过可观测性追踪,粗略验证了 前文对 “Ib_logfile的checkpoint field”的描述准确性。

理论依据

事务日志或称redo日志,在MySQL中默认以ib_logfile0,ib_logfile1名称存在,可以手工修改参数,调节开启几组日志来服务于当前MySQL数据库,MySQL采用顺序,循环写方式,每开启一个事务时,会把一些相关信息记录事务日志中(记录对数据文件数据修改的物理位置或叫做偏移量);

这个系列文件个数由参数innodb_log_files_in_group​控制,若设置为4,则命名为ib_logfile0~3

这些文件的写入是顺序、循环写的,logfile0​写完从logfile1​继续,logfile3​写完则logfile0继续。

在系统崩溃重启时,作事务重做;在系统正常时,每次checkpoint时间点,会将之前写入事务应用到数据文件中。

Ib_logfile的checkpoint field

实际上不仅要记录checkpoint​做到哪儿(LOG_CHECKPOINT_LSN)​,还要记录用到了哪个位置(LOG_CHECKPOINT_OFFSET)​等其他信息。所以在ib_logfile0的头部预留了空间,用于记录这些信息。

因此即使使用后面的logfile​,每次checkpoint​完成后,ib_logfile0都是要更新的。同时你会发现所谓的顺序写盘,也并不是绝对的

相关的一些数字

a) InnoDB​留了两个checkpoint filed​,按照注释的解释,目的是为了能够“write alternately”

b) 每个checkpint field需要的大小空间为304字节。(相关定义在log0log.h)

c) 第一个checkpoint​的起始位置在ib_logfile0​的第512字节(OS_FILE_LOG_BLOCK_SIZE)处;

d) “第二个在1536 (3 * OS_FILE_LOG_BLOCK_SIZE)字节处” [^引1]

Redo log​文件以ib_logfile[number]​命名,日志目录可以通过参数innodb_log_group_home_dir​控制。Redo log​以顺序的方式写入文件文件,写满时则回溯到第一个文件,进行覆盖写。(但在做redo checkpoint​时,也会更新第一个日志文件的头部checkpoint标记,所以严格来讲也不算顺序写)。

“在InnoDB内部,逻辑上ib_logfile被当成了一个文件,对应同一个space id。由于是使用512字节block对齐写入文件,可以很方便的根据全局维护的LSN号计算出要写入到哪一个文件以及对应的偏移量。”[^引2]

总结

8.0 一个自动提交事务,redo落文件的方式追踪 1.通过后台线程thread/innodb/log_writer_thread ​写redo,通过另一个后台线程thread/innodb/log_checkpointer_thread​ ,在ib_logfile0的pos=512 pos=1536 ,分别记录checkpoint 。两个线程都是以512B的整数倍为单位,写文件。

追踪过程比结论重要。sysdig在可观测性方面提供了强大的帮助。理论联系实际,才是探索未知事务之道。

参考资料

[1][^引1]:  ib_logfile和mysql_bin_MySQL的InnoDB引擎中事务日志ib_logfile0和ib_logfile1详解: https://blog.csdn.net/weixin_36271649/article/details/113154646

[2][^引2]: InnoDB redo log漫游: https://developer.aliyun.com/article/219

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/253682.html<

(0)
运维的头像运维
上一篇2025-04-30 00:40
下一篇 2025-04-30 00:42

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注