爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1500 字,预计阅读需要 3 分钟。
想必在日常运维 MySQL 的过程中,无论是主从搭建、版本升级、数据迁移,还是定期巡检,我们总会遇到需要对比 MySQL 配置的场景。这种看似简单的需求,实际操作中隐藏着很多细节和挑战。
虽然已有 pt-config-diff[1] 类似的工具可以使用,但在一些定制化运维场景中,不可避免地需要自己去实现相关代码。
当我们想要实现一个 MySQL 配置对比脚本时,需要考虑的那些关键点和容易被忽略的细节?让我们开始下面的内容。
模拟场景:针对同一实例,如何对比变量的运行值、配置文件值?
既然要对比变量的运行值与配置文件中的配置值(后文均以运行值和配置值简述),我们便从如何获取对应的值说起。
首先,获取变量的运行值。
[root@localhost ~]$ /opt/sandboxes/mysql/5.7.31/bin/mysql --login-path=root --socket=/tmp/mysql_sandbox5731.sock -se "SHOW VARIABLES LIKE 'transaction_isolation';" | awk '{print $2}'
REPEATABLE-READ
当然,你也可以直接查询 performance_schema.global_variables
表。
[root@localhost ~]$ /opt/sandboxes/mysql/5.7.31/bin/mysql --login-path=root --socket=/tmp/mysql_sandbox5731.sock -se "select * from performance_schema.global_variables where variable_name = 'transaction_isolation'" | awk '{print $2}'
REPEATABLE-READ
可以看到,运行值的获取较为简单。当然,在通过脚本执行时,不可避免地需要使用明文密码,这里有两个建议:
--login-path=root
参数,相比明文密码安全一些。在说明配置值如何获取前,我们考虑下除了运行值,还有哪些可能影响变量的文件?
推荐的运维场景下,一般使用 --defaults-file
参数指定配置文件,这样做有几点好处:
--defaults-file
获取配置文件的位置。/etc/my.cnf
等其他配置文件的干扰。除了默认的配置文件,在 MySQL 8.0 中,还需考虑被持久化的变量配置文件,即 mysqld-auto.cnf
。
有时我们会在启动 mysqld 进程时手工指定某些参数配置,此时也会影响对应的变量值。这种启动方式一般仅用于临时维护使用,本文暂不考虑。
针对 my.cnf
文件中配置值的获取,这里我提供一些需要考虑的场景供大家参考:
port
、socket
等变量配置,在 [mysql]
、[mysqld]
等标签中均有配置,在获取时需要先过滤出配置文件中关于 [mysqld]
的部分。key
和 value
。常见的有:port=3306 # 端口
格式的注释,在获取值时需要使用 awk 或 sed 进行处理。key=value
这种紧凑的格式后再进行匹配过滤。.
进行模糊匹配。至此,我们已经获取了 my.cnf
配置文件中的变量名及其对应的值。接下来我们一起看看 mysqld-auto.cnf
,以下是一个简化的 mysqld-auto.cnf
文件内容示例:
[root@localhost data]$ cat mysqld-auto.cnf | jq
{
"Version": 2,
"mysql_static_variables": {
"innodb_buffer_pool_size": {
"Value": "1073741824",
"Metadata": {
"Host": "localhost",
"User": "msandbox",
"Timestamp": 1734599734016339
}
}
},
"mysql_dynamic_parse_early_variables": {
"max_connections": {
"Value": "5000",
"Metadata": {
"Host": "localhost",
"User": "msandbox",
"Timestamp": 1734599700972489
}
}
}
}
这里提供两种思路获取对应的 key
和 value
。
[root@localhost data]$ cat mysqld-auto.cnf | jq | awk '
function clean_str(s) {
gsub(/^ *"|"|:|,$/, "", s)
return s
}
/^ *"[^"]+": *{$/ {
k = clean_str($1)
}
/^ *"Value": *"[^"]*"/ {
sub(/^ *"Value": *"/, "", $0)
print k ":" clean_str($0)
}
'
# 输出示例
innodb_buffer_pool_size:1073741824
max_connections:5000
jq
命令[root@localhost data]$ jq -r 'to_entries[] | select(.value | type == "object") | .value | to_entries[] | select(.value | has("Value")) | .key + ":" + .value.Value' mysqld-auto.cnf
# 输出示例
innodb_buffer_pool_size:1073741824
max_connections:5000
在我们已经获取了运行值、不同配置文件的有效配置值之后,如何来进行对比呢?如果你想到的只是使用 ==
进行判断,或许结果会有很大一部分存在误判,你还需要考虑以下几点:
key
和 value
的大小写进行统一。在 MySQL 配置对比的实现中,你需要综合考虑多种因素,不断地优化完善代码,才能实现准确可靠的配置对比功能。
本文旨在提供一些较为常见的实现思路,如有其他场景,欢迎大家一起交流。
参考资料
[1]
pt-config-diff: https://docs.percona.com/percona-toolkit/pt-config-diff.html
本文关键字:#MySQL# #配置文件# #pt-config-diff# #my.cnf#