引言 #
MySQL的复制功能是保持多个数据库服务器之间数据一致性的关键特性。对于数据库管理员和开发人员来说,了解这个过程中涉及的线程非常重要。在这篇博文中,我们将探讨如何通过修改MySQL的源代码来自定义这些线程的名称。
MySQL复制线程的官方说明 #
MySQL官方文档对复制线程的描述如下:
MySQL replication capabilities are implemented using the following types of threads:
Binary log dump thread. The source creates a thread to send the binary log contents to a replica when the replica connects. This thread can be identified in the output of SHOW PROCESSLIST on the source as the Binlog Dump thread.
Replication I/O receiver thread. When a START REPLICA statement is issued on a replica server, the replica creates an I/O (receiver) thread, which connects to the source and asks it to send the updates recorded in its binary logs.
The replication receiver thread reads the updates that the source’s Binlog Dump thread sends (see previous item) and copies them to local files that comprise the replica’s relay log.
The state of this thread is shown as Slave_IO_running in the output of SHOW REPLICA STATUS.
Replication SQL applier thread. When replica_parallel_workers is equal to 0, the replica creates an SQL (applier) thread to read the relay log that is written by the replication receiver thread and execute the transactions contained in it. When replica_parallel_workers is N >= 1, there are N applier threads and one coordinator thread, which reads transactions sequentially from the relay log, and schedules them to be applied by worker threads. Each worker applies the transactions that the coordinator has assigned to it.
翻译:
MySQL的复制功能通过以下类型的线程实现:
二进制日志发送线程(Binary log dump thread):当从库连接到主库时,主库会创建一个线程来向从库发送二进制日志的内容。这个线程在主库的 SHOW PROCESSLIST 输出中可以被识别为 Binlog Dump 线程。
复制I/O接收线程(Replication I/O receiver thread):当在从库上发出 START REPLICA 语句时,从库创建一个I/O(接收)线程,该线程连接到主库,并请求主库发送其二进制日志中记录的更新。
复制接收线程读取由主库的 Binlog Dump 线程发送的更新,并将它们复制到构成从库中继日志的本地文件中。
这个线程的状态在 SHOW REPLICA STATUS 的输出中显示为 Slave_IO_running。
复制SQL应用线程(Replication SQL applier thread):当 replica_parallel_workers 等于0时,从库创建一个SQL(应用)线程来读取由复制接收线程写入的中继日志,并执行其中包含的事务。当 replica_parallel_workers 为 N >= 1时,有N个应用线程和一个协调线程,该协调线程从中继日志中顺序读取事务,并安排它们由工作线程应用。每个工作者应用由协调者分配给它的事务。
更多详细信息,请参考 MySQL 8.4 Reference Manual - Replication Threads。
实验:自定义线程名称 #
我们将重点修改"Binlog Dump"线程的名称,以演示自定义MySQL内部线程名称的过程。
步骤1:设置环境 #
确保你已经设置好MySQL开发环境。你需要:
- MySQL源代码
- 编译好的MySQL版本
- 一个运行中的、配置了复制的MySQL实例
注意:本实验假设主从复制已经搭建完成,搭建主从过程在此省略。
步骤2:查看原始线程名称 #
启动MySQL服务:
./bin/mysqld --defaults-file=/home/grok/mysql-server/build/my.cnf
查看复制线程状态:
mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'repl_user';
+----+-----------+-----------------------+------+-------------+------+-----------------------------------------------------------------+------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+----+-----------+-----------------------+------+-------------+------+-----------------------------------------------------------------+------+
| 15 | repl_user | 192.168.144.129:36400 | NULL | Binlog Dump | 38 | Source has sent all binlog to replica; waiting for more updates | NULL |
+----+-----------+-----------------------+------+-------------+------+-----------------------------------------------------------------+------+
1 row in set (0.00 sec)
可以看到线程名称是 Binlog Dump。
步骤3:修改源代码 #
关闭MySQL服务:
mysql> shutdown;
修改 /home/grok/mysql-server/sql/sql_parse.cc
文件中的 Command_names::m_names
数组:
const std::string Command_names::m_names[] = {
"Sleep",
"Quit",
"Init DB",
"Query",
"Field List",
"Create DB",
"Drop DB",
"Refresh",
"Shutdown",
"Statistics",
"Processlist",
"Connect",
"Kill",
"Debug",
"Ping",
"Time",
"Delayed insert",
"Change user",
"Binlog Dump", // 将这一行修改为 "grok Binlog Dump",
"Table Dump",
"Connect Out",
"Register Replica",
"Prepare",
"Execute",
"Long Data",
"Close stmt",
"Reset stmt",
"Set option",
"Fetch",
"Daemon",
"Binlog Dump GTID",
"Reset Connection",
"clone",
"Group Replication Data Stream subscription",
"Error" // Last command number
};
步骤4:重新编译MySQL #
进入 MySQL 源码目录并重新编译:
cd /home/grok/mysql-server/build
make
步骤5:重启MySQL并验证更改 #
重新启动MySQL服务:
./bin/mysqld --defaults-file=/home/grok/mysql-server/build/my.cnf
进入MySQL命令行:
./bin/mysql -uroot -p -S/home/grok/mysql-server/build/data/mysql.sock
查看更改后的线程名称:
mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'repl_user';
+----+-----------+-----------------------+------+------------------+-------+-----------------------------------------------------------------+------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+----+-----------+-----------------------+------+------------------+-------+-----------------------------------------------------------------+------+
| 15 | repl_user | 192.168.144.129:48182 | NULL | grok Binlog Dump | 59974 | Source has sent all binlog to replica; waiting for more updates | NULL |
+----+-----------+-----------------------+------+------------------+-------+-----------------------------------------------------------------+------+
1 row in set (0.00 sec)
可以看到 COMMAND 列中的线程名字已经改变成我们定义的 “grok Binlog Dump”。
结论 #
通过修改MySQL的源代码,我们成功自定义了内部线程名称,使得识别和跟踪特定进程变得更加容易。这对于调试、监控和理解MySQL复制的复杂性特别有用。
请记住,修改源代码应该谨慎进行,没有经过彻底测试不建议在生产环境中使用。
参考资料 #
注意:本实验是在受控的开发环境中进行的。在对生产系统应用任何更改之前,请务必备份数据并进行彻底测试。