各位观众老爷,晚上好!我是今天的主讲人,江湖人称“代码老司机”。今天咱们不飙车,聊聊MySQL主从复制这辆“老爷车”的内部引擎——Binlog、IO线程和SQL线程的生命周期。
开场白:主从复制,一场精心策划的“拷贝秀”
话说,数据这玩意儿,就像金子,越多越好。但单机MySQL,再牛逼也怕宕机,万一服务器罢工,数据就GG了。所以,我们需要备份,需要冗余。于是,主从复制就应运而生了!
主从复制,简单来说,就是把一台MySQL服务器(Master,主库)上的数据,实时同步到另一台或多台MySQL服务器(Slave,从库)上。这样,即使主库挂了,从库也能顶上,保证业务的连续性。这就像古代皇帝有太子一样,随时准备接班。
第一幕:Binlog——事件的忠实记录者
要实现主从复制,首先得有个“日记本”,记录主库上发生的所有数据变更事件。这个“日记本”就是Binlog(Binary Log,二进制日志)。
-
Binlog的格式:
Binlog的格式决定了从库如何解析和应用主库的变更。常见的Binlog格式有三种:
- STATEMENT(语句级复制): 记录SQL语句。优点是日志量小,缺点是某些语句(如包含
NOW()
、RAND()
等函数的语句)可能导致主从数据不一致。 - ROW(行级复制): 记录每一行的变更。优点是数据一致性高,缺点是日志量大。
- MIXED(混合模式复制): 混合使用STATEMENT和ROW格式。MySQL会根据语句的特性自动选择合适的格式。
如何查看当前的Binlog格式?
SHOW VARIABLES LIKE 'binlog_format';
如何设置Binlog格式?
SET GLOBAL binlog_format = ROW; -- 推荐使用ROW格式
- STATEMENT(语句级复制): 记录SQL语句。优点是日志量小,缺点是某些语句(如包含
-
Binlog的生命周期:
- 产生: 当主库执行写操作(INSERT、UPDATE、DELETE等)时,会将这些操作记录到Binlog中。
- 存储: Binlog以二进制文件的形式存储在主库服务器上。
- 轮转: 为了防止Binlog文件过大,MySQL会定期轮转Binlog文件。轮转策略由
max_binlog_size
和expire_logs_days
两个参数控制。 - 删除: 过期的Binlog文件会被自动删除。
如何查看Binlog列表?
SHOW BINARY LOGS;
如何查看Binlog内容?(需要使用
mysqlbinlog
工具)mysqlbinlog mysql-bin.000001
第二幕:IO线程——信息的搬运工
有了Binlog这个“日记本”,接下来就需要一个“搬运工”,将Binlog的内容从主库搬到从库。这个“搬运工”就是IO线程。
-
IO线程的角色:
IO线程运行在从库上,负责连接主库,并向主库请求Binlog。主库收到请求后,会将Binlog的内容发送给IO线程。IO线程接收到Binlog内容后,将其写入到从库的Relay Log(中继日志)中。
-
IO线程的生命周期:
- 连接: 从库启动时,IO线程会根据配置信息(主库IP、端口、用户名、密码等)连接到主库。
- 请求: IO线程会向主库发送请求,索要指定位置的Binlog。
- 接收: 主库收到请求后,会将Binlog的内容发送给IO线程。
- 写入: IO线程接收到Binlog内容后,将其写入到从库的Relay Log中。
- 循环: IO线程会不断地重复上述过程,直到从库停止复制。
如何查看IO线程的状态?
SHOW SLAVE STATUSG
关注
Slave_IO_Running
字段,如果为Yes
,则表示IO线程正在运行。 -
IO线程的配置:
在从库的配置文件(my.cnf或my.ini)中,需要配置以下参数:
server-id
:从库的唯一ID。relay-log
:Relay Log文件的路径。log-slave-updates
:是否将从库的更新操作记录到Relay Log中。(如果从库也作为其他从库的主库,则需要开启此选项)master-host
:主库的IP地址。master-port
:主库的端口号。master-user
:连接主库的用户名。master-password
:连接主库的密码。
配置完成后,需要重启从库。
第三幕:SQL线程——指令的执行者
Relay Log就像一个“待办事项列表”,记录了所有需要在从库上执行的SQL语句。接下来就需要一个“执行者”,按照顺序执行这些SQL语句。这个“执行者”就是SQL线程。
-
SQL线程的角色:
SQL线程运行在从库上,负责读取Relay Log中的SQL语句,并在从库上执行。
-
SQL线程的生命周期:
- 读取: SQL线程会从Relay Log中读取SQL语句。
- 执行: SQL线程会在从库上执行读取到的SQL语句。
- 循环: SQL线程会不断地重复上述过程,直到Relay Log为空。
如何查看SQL线程的状态?
SHOW SLAVE STATUSG
关注
Slave_SQL_Running
字段,如果为Yes
,则表示SQL线程正在运行。 -
SQL线程的优化:
SQL线程的执行速度直接影响从库的延迟。为了提高SQL线程的执行效率,可以采取以下措施:
- 多线程复制: MySQL 5.7开始支持多线程复制,可以将SQL线程拆分成多个线程,并行执行Relay Log中的SQL语句。
- 优化SQL语句: 确保SQL语句的执行效率,避免慢查询。
- 调整参数: 调整
slave_parallel_workers
参数,设置SQL线程的数量。
幕间休息:主从延迟的罪魁祸首
主从延迟是指从库的数据落后于主库的数据。主从延迟是主从复制中常见的问题,影响业务的正常运行。导致主从延迟的原因有很多,常见的有:
- 网络延迟: 主从服务器之间的网络延迟会导致Binlog的传输速度变慢。
- 主库压力过大: 主库的写压力过大,导致Binlog的写入速度变慢。
- 从库压力过大: 从库的SQL线程执行速度跟不上主库的Binlog写入速度。
- 锁竞争: 从库上存在大量的锁竞争,导致SQL线程的执行效率降低。
- 大事务: 主库上执行的大事务会导致从库的延迟增加。
如何解决主从延迟?
- 优化硬件: 提升主从服务器的硬件配置,如CPU、内存、磁盘等。
- 优化网络: 确保主从服务器之间的网络连接稳定、带宽充足。
- 优化SQL语句: 避免慢查询,减少锁竞争。
- 使用多线程复制: 提高SQL线程的执行效率。
- 分库分表: 将数据分散到多个数据库或表中,降低单库的压力。
实战演练:搭建一个简单的主从复制环境
为了让大家更好地理解主从复制的原理,咱们来搭建一个简单的主从复制环境。
-
环境准备:
- 两台MySQL服务器(一台作为主库,一台作为从库)。
- 确保两台服务器可以互相访问。
- 关闭防火墙。
-
配置主库:
-
修改主库的配置文件(my.cnf或my.ini):
[mysqld] server-id = 1 # 主库的ID log_bin = mysql-bin # 开启Binlog binlog_format = ROW # 设置Binlog格式为ROW expire_logs_days = 7 # 设置Binlog过期时间为7天 #binlog_do_db = your_database # 可选,指定需要同步的数据库 #binlog_ignore_db = your_database # 可选,指定需要忽略同步的数据库
-
重启主库。
-
创建一个用于复制的用户:
CREATE USER 'repl'@'%' IDENTIFIED BY 'your_password'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;
-
锁定主库,并获取Binlog的位置:
FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;
记录
File
和Position
的值,稍后需要在从库上使用。 -
解锁主库:
UNLOCK TABLES;
-
-
配置从库:
-
修改从库的配置文件(my.cnf或my.ini):
[mysqld] server-id = 2 # 从库的ID,必须与主库不同 relay-log = mysql-relay-bin # 开启Relay Log log-slave-updates = 1 # 如果从库也作为其他从库的主库,则需要开启此选项 master-host = 主库的IP地址 master-port = 3306 # 主库的端口号 master-user = repl # 连接主库的用户名 master-password = your_password # 连接主库的密码 replicate-do-db = your_database # 可选,指定需要同步的数据库 replicate-ignore-db = your_database # 可选,指定需要忽略同步的数据库
-
重启从库。
-
配置从库连接主库:
CHANGE MASTER TO MASTER_HOST='主库的IP地址', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='your_password', MASTER_LOG_FILE='记录的File值', MASTER_LOG_POS=记录的Position值;
-
启动从库的复制功能:
START SLAVE;
-
查看从库的状态:
SHOW SLAVE STATUSG
检查
Slave_IO_Running
和Slave_SQL_Running
是否都为Yes
。如果都为Yes
,则表示主从复制已经成功建立。
-
-
测试:
- 在主库上创建一个数据库和表,并插入一些数据。
- 在从库上查看是否同步了主库的数据。
高级技巧:GTID复制
传统的基于Binlog位置的复制方式,在主从切换时容易出现问题。GTID(Global Transaction Identifier,全局事务ID)复制是一种更加可靠的复制方式。
-
GTID的原理:
GTID是MySQL为每个事务分配的唯一ID。GTID由
server_uuid
和transaction_id
两部分组成。server_uuid
是服务器的唯一ID,transaction_id
是事务的序列号。在GTID复制中,从库会记录已经执行的GTID,并根据GTID来判断是否需要执行某个事务。这样,即使主从服务器之间发生切换,从库也能正确地找到需要执行的事务。
-
配置GTID复制:
-
修改主库和从库的配置文件(my.cnf或my.ini):
[mysqld] gtid_mode = ON enforce_gtid_consistency = ON log_slave_updates = 1
-
重启主库和从库。
-
配置从库连接主库:
CHANGE MASTER TO MASTER_HOST='主库的IP地址', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='your_password', MASTER_AUTO_POSITION=1; # 使用GTID自动定位
-
启动从库的复制功能:
START SLAVE;
-
查看从库的状态:
SHOW SLAVE STATUSG
检查
Slave_IO_Running
和Slave_SQL_Running
是否都为Yes
,并且Last_IO_Error
和Last_SQL_Error
是否为空。
-
总结陈词:主从复制,永不过时的经典
主从复制是MySQL中一项非常重要的技术,它可以提高数据的可靠性和可用性。虽然现在有很多新的复制技术,但主从复制仍然是很多企业的首选方案。理解主从复制的原理,掌握其配置和优化技巧,对于每一个MySQL DBA来说都是至关重要的。
希望今天的讲座能对大家有所帮助。谢谢大家!
(讲座结束,老司机挥手告别)