前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[MYSQL] mysql.err 在蹦迪? (未找到原因)

[MYSQL] mysql.err 在蹦迪? (未找到原因)

原创
作者头像
大大刺猬
修改2024-05-31 18:18:41
1150
修改2024-05-31 18:18:41
举报
文章被收录于专栏:大大刺猬大大刺猬

导读

今天遇到一个离谱的问题, mysql的error日志mysql.err文件 大小会变化, 偶尔猛增, 然后过一会又降下来... 过一会又猛涨, 每次涨的幅度都是一样的. 然后过大概1个月, 涨幅又翻倍. 过3个月又降下来,重新开始涨, 每月1周期,3月1轮回

环境

x86

rhel 8.6

multipath

mysql 5.7.41

从库

MTS

未配置日志轮转等

详情

生产环境,不方便放截图, 就画个类似的图吧. 监控的虽然是文件系统, 但排查下来就只有mysql.err这个文件有这种变化. 差不多就每隔一段时间就会涨上去, 然后过一会就会降下来, 很有规律..

说明: 纵坐标可以当作是du -sh mysql.err文件大小. 横坐标是时间.

每隔一段时间, 这个涨幅就会翻倍. 看起来像是操作系统/文件系统的问题, 但日志里面没得任何记录(除了用户登录之类的外). 难道是玄学问题?

猜测:

du 和 df 看到的大小才有这个波动, 如果是使用ls -l或者stat看到的就是无变化的, 即一条直线.

也就是比较像是 文件系统 预分配空间给 mysql.err文件, 导致du/df看到的空间比较大, 但ls/stat看到的还是记录值. 由于后续未使用到, 所有又偷偷回收回去了? 但这预分配的空间有实际占用空间的一半了. 是不是有点大?

结论

暂无结论, 也没找到相关BUG.

后续有结论了再说吧

原因

原因找到了, 就是我们猜测的那样, 也就是xfs文件系统的锅, 也不能说是锅吧.

当写入比较频繁的时候, 会申请 1/2 当前文件大小的空间, du能看到, 但是ls看不到(未实际使用).

当写入不频繁的时候, 会慢慢回收掉预分配的空间 XFS:程序小老弟,你咋回事,给你空间,你咋个不用呢

我模拟的时候, 使用os.fsync也不会回收预分配空间, 只有慢慢写入才会回收.

RHEL将其称为 定性预分配 Speculative preallocation 描述如下, 基本上符合我们看到的现象

XFS uses speculative preallocation to allocate blocks past EOF as files are written. This avoids file fragmentation due to concurrent streaming write workloads on NFS servers. By default, this preallocation increases with the size of the file and will be apparent in "du" output. If a file with speculative preallocation is not dirtied for five minutes the preallocation will be discarded. If the inode is cycled out of cache before that time, then the preallocation will be discarded when the inode is reclaimed. If premature ENOSPC problems are seen due to speculative preallocation, a fixed preallocation amount may be specified with the -o allocsize=amount mount option.

原文: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/migrating-ext4-xfs

复现方法

  1. 清空error log (方便观察)
  2. 产生大量error log (模拟程序异常断开就行, 反正开发也不喜欢正常关闭连接)
  3. 产生小量error log

观察期间的error log大小

代码语言:python
代码运行次数:0
复制
# 模拟大量日志
import pymysql
import time
while True:
	conn = pymysql.connect(
			host='192.168.101.202',
			port=3306,
			user='u1',
			password='xx',
			)
	#conn.close() # 不主动断开
	time.sleep(0.01)

# 跑2秒就行了, 然后ctrl+c 看下error log文件大小
SEHLL> du -sh mysql.err && ls -lh mysql.err && date

# 模拟小量日志
import pymysql
import time
while True:
	conn = pymysql.connect(
			host='192.168.101.202',
			port=3306,
			user='u1',
			password='xx',
			)
	#conn.close()
	time.sleep(30)

# 慢慢等, 这里会等很久....
# 然后再观察error log

我这里测试了多次, 所以空间不是 1/2, 它这具体的比例和算法,咱也不知道.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导读
  • 环境
  • 详情
  • 猜测:
  • 结论
  • 原因
  • 复现方法
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档