网站建设知识
MySQL高可用方案之多级复制
2025-07-22 09:57  点击:0

在大部分场景中我们都是用MySQL主从复制来实现数据库的冗余,这里是用多级复制来处理,多级复制可以快速简单的处理数据库的故障,数据库有A、B、C服务器,正常情况下A为主、B为A的从、C为B的从。

A-->B-->C

当A出现问题时,将B设为主,C为B的从,A正常后就为C的从

B-->C-->A

当B出问题后,C为主,A为C的从,B为A的从,如此反复可以快速解决问题

角色IP主机名数据库版本
192.168.2.241db15.6.29
192.168.2.242db25.6.29
192.168.2.243db35.6.29

注意在这样的场景下数据库的版本必须为一致,否则会因为版本之间不兼容导致出现问题

创建复制账户

配置数据库配置

备份主库,然后导入到备库

配置主从

1.创建复制账户

mysql>grantrepicationslaveon*.*to'repl'@'192.168.2.%'identifiedby'repl';mysql>flushprivileges;

2.开启数据库binlog,设置server-id和启用log_slave_updates

说明:log_slave_updates是将从服务器从主服务器收到的更新记入到从服务器自己的二进制日志文件中

如果没有开启log_slave_updates则在A-->B-->C场景中,C将无法从B中获取到数据

在MySQL配置文件/etc/my.cnf中的[mysqld]下添加如下语句

log-bin=mysqlbinserver-id=241#这里每台服务器都必须不一致,最好是IP的末段log_slave_updates=1expire_logs_days=7

记得重启下数据库

3.备份主库,然后导入到备库中

锁表

mysql>flushtableswithreadlock;mysql>showmasterstatus;+---------------+----------+--------------+------------------+-------------------+|File|Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set|+---------------+----------+--------------+------------------+-------------------+|binlog.000002|409||||+---------------+----------+--------------+------------------+-------------------+1rowinset(0.00sec)

注意:这里不能退出mysql命令行会话,另外再开一个窗口将数据库导出,因为锁表的时候,只要退出会话锁表自动解除

[root@db1~]#mysqldump-uroot-p--all-database--add-drop-table>all_database.sql

将上面导出的all_database.sql导入到其他的db2、db3中

[root@db2~]#mysql-uroot-p
[root@db3~]#mysql-uroot-p<all_database.sql< pre=""><p>4.开启主从复制</p><p>在db2上:</p><pre class="brush:sql;toolbar:false">mysql>changemastertomaster_host='192.168.2.241',master_user='repl',master_password='repl',master_log_file='binlog.000002',master_log_pos=409;mysql>startslave;mysql>showmasterstatus;+---------------+----------+--------------+------------------+-------------------+|File|Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set|+---------------+----------+--------------+------------------+-------------------+|binlog.000002|647569||||+---------------+----------+--------------+------------------+-------------------+</pre><p>在db3上:</p><pre class="brush:sql;toolbar:false">mysql>changemastertomaster_host='192.168.2.242',master_user='repl',master_password='repl',master_log_file='binlog.000002',master_log_pos=647569;mysql>startslave;</pre><p>然后分别在db2和db3上执行show slave status\G;查看是否有错</p><pre class="brush:sql;toolbar:false">mysql>showslavestatus\G;***************************1.row***************************Slave_IO_State:WaitingformastertosendeventMaster_Host:192.168.2.242Master_User:replMaster_Port:3306Connect_Retry:60Master_Log_File:binlog.000002Read_Master_Log_Pos:647569Relay_Log_File:db3-relay-bin.000002Relay_Log_Pos:280Relay_Master_Log_File:binlog.000002Slave_IO_Running:YesSlave_SQL_Running:YesReplicate_Do_DB:Replicate_Ignore_DB:Replicate_Do_Table:Replicate_Ignore_Table:Replicate_Wild_Do_Table:Replicate_Wild_Ignore_Table:Last_Errno:0Last_Error:Skip_Counter:0Exec_Master_Log_Pos:647569Relay_Log_Space:451Until_Condition:NoneUntil_Log_File:Until_Log_Pos:0Master_SSL_Allowed:NoMaster_SSL_CA_File:Master_SSL_CA_Path:Master_SSL_Cert:Master_SSL_Cipher:Master_SSL_Key:Seconds_Behind_Master:0Master_SSL_Verify_Server_Cert:NoLast_IO_Errno:0Last_IO_Error:Last_SQL_Errno:0Last_SQL_Error:Replicate_Ignore_Server_Ids:Master_Server_Id:242Master_UUID:25a2315a-d9f0-11e5-9aa9-000c296e3855Master_Info_File:/var/lib/mysql/master.infoSQL_Delay:0SQL_Remaining_Delay:NULLSlave_SQL_Running_State:Slavehasreadallrelaylog;waitingfortheslaveI/OthreadtoupdateitMaster_Retry_Count:86400Master_Bind:Last_IO_Error_Timestamp:Last_SQL_Error_Timestamp:Master_SSL_Crl:Master_SSL_Crlpath:Retrieved_Gtid_Set:Executed_Gtid_Set:Auto_Position:01rowinset(0.00sec)</pre><p>可以看到</p><p>Slave_IO_Running: Yes</p><p>Slave_SQL_Running: Yes</p><p>为yes,说明复制正常</p><p></p><p>接着测试一下:</p><p>在数据库中插入数据,然后在db1、db2、db3上查询即可</p><p></p><p>如有问题可以show slave status\G;查看是否有错误</p><p>如果遇到类似1062的错误的话可以忽略,则可以直接</p><pre class="brush:sql;toolbar:false">mysql>stopslave;mysql>SETGLOBALSQL_SLAVE_SKIP_COUNTER=1;mysql>startslave;</pre><p>在运行一段时间后,db1出现问题,导致无法恢复的故障,则只需要在db2上执行stop slave;</p><p>然后db1恢复后,从db3导出数据并记录点,然后change master到db3上</p><p>如果为了防止在从库意外写入,也可以在从数据库的配置文件中加入read_only = 1</p><p></p><p></p><p></p><p></p></all_database.sql<>
se.sql<>