安装好Docker + MySQL 8 (Docker Hub 官方镜像)
主服务器my.cnf配置(Docker里面安装的MySQL配置文件在/etc/mysql/my.cnf)
log_bin = /var/lib/mysql/mysql-bin // 这里mysql-bin只是日志文件的路径(如果没有指定目录,默认就在datadir目录)和文件名前缀,可以自己取,生成的日志文件应该是 mysql-bin.000001.log类似的,实际上我一般用服务器名/var/lib/mysql/server1,这样在拷贝日志文件到其他地方是更容易区分
server_id = 10 // 服务器ID,默认是1,所有所有mysql默认都是这个值,为了防止不必要的冲突,我们一般设置为服务器IP地址4段中的最后一段,比如服务器IP是 172.17.0.10
sync_binlog = 1 // 可选,每次提交事务前先写日志。这样在服务器崩溃时不会因为日志没有写入而丢失事件和数据(最多丢失最后的一条),但对性能影响可能较大,建议设置为2-100,这样我们相当于允许2-100个操作丢失
binlog_format = ROW // 使用基于行的日志格式
为从服务器创建主从复制用账号,处于安全考虑,我们限制账号只能从127.12.0.xxx的网段访问
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'127.12.0.%'; // REPLICATION CLIENT权限是可选的,但用来监控和管理复制(复制用户可以使用 SHOW MASTER STATUS, SHOW SLAVE STATUS和 SHOW BINARY LOGS来确定复制状态)的账号需要这个权限,一般这个管理账号我们用的是和复制服务相同的账号(当然可以不同,只是没有那么方便),另外也方便以后切换主从服务器,因为通过复制同步,从库也具有了相同的账号配置
注意:如果需要创建数据库和删除数据库的权限,那么也需要赋予Create和Drop权限
ALTER USER 'repl'@'127.12.0.%' IDENTIFIED WITH mysql_native_password BY 'password' PASSWORD EXPIRE NEVER;
FLUSH PRIVILEGES;
重启MySQL,进入MySQL执行
SHOW MASTER STATUS;
可以看到主服务器生成的日志文件名和当前日志记录到了第几行
从服务器my.cnf配置
log_bin = mysql-bin
server-id = 20 // 比如服务器IP是 172.17.0.20
relay_log = /var/lib/mysql/mysql-relay-bin // 可选,指定中继日志的位置和命名,默认就是在这个位置
log_slave_updates = 1 // 可选,允许从服务器将重放的事件也记录到自身的二进制日志中,这个选项和导致从库增加额外的日志和工作负担,但因为写了日志,那么其他从服务器就可以直接从这台从服务器做复制,而不需要都直连主服务器(当从服务器很多时,可以很好的减轻主服务器的负担),当把这台从服务器切换为主服务器时,其他从服务器也不需要变更配置
read_only = 1 // 可选,设置从库为只读,如过从库也需要修改则不要设置,这里设置是为了防止有人意外修改从库数据
binlog_format = ROW // 使用基于行的日志格式
重启MySQL,进入MySQL执行
CHANGE MASTER TO MASTER_HOST='172.17.0.10',
MASTER_USER='repl', MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
这样就做好了连接配置,并启用了复制功能
这里我们设置MASTER_LOG_POS=0,那么复制服务就会从mysql-bin.000001的第0行开始复制,如果不需要从头开始复制的话,就可以按自己的需要设置
执行状态查看
SHOW SLAVE STATUSG;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 172.17.0.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: c9599634ed84-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
Last_Errno: 0
Last_Error:
可以看到配置已经生效,只是还没有开始复制
启动复制
START SLAVE;
再次查看状态
SHOW SLAVE STATUSG;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: c9599634ed84-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_Errno: 0
Last_Error:
可以看到复制服务已经启动了,且状态是等待主服务器发送事件,如果有问题,就要查看Last_Errno,然后具体排查
现在如果主服务器执行sql,就会在从服务器看到也同样执行了
过滤器
注意:基于语句的日志模式 binlog_format = STATEMENT 时强烈建议不要使用(基于行的日志模式不会有这个问题),会导致各种问题和数据丢失
因为过滤实际上不是过滤某个数据库所属的操作,而是过滤在当前数据库上执行的语句中带有数据库前缀的语句操作,比如:
use test1;
delete from test2.table1;
实际上只是在test1上没有执行这个语句,在test2上会执行
# 不同步哪些数据库
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
# 只同步哪些数据库,除此之外,其他不同步
binlog-do-db = game
如果需要修改配置,需要先停止服务服务
STOP SLAVE;