Replication enables data from one MySQL database server (the source) to be copied to one or more MySQL database servers (the replicas). Replication is asynchronous by default; replicas do not need to be connected permanently to receive updates from the source. Depending on the configuration, you can replicate all databases, selected databases, or even selected tables within a database.
复制使数据可以从一台MySQL数据库服务器(源)复制到一台或多台MySQL数据库服务器(副本)。默认情况下,复制是异步的;副本无需永久连接即可从源接收更新。根据配置,您可以复制数据库中的所有数据库,选定的数据库甚至选定的表。
应用场景:
基于实际业务,我们的使用场景有以下方面:
一般来说,我觉得除了官方文档,网上任何的文章图表都只能作为灵感来源,而不能作为决定依据。因此我们的参考文档肯定就是mysql的官方文档啦,纯英文看起来比较费劲,搭配谷歌浏览器的翻译食用风味更佳(官方文档上有更为详细的介绍,这里只做抛砖引玉,引入基本的概念和操作,更为详细的使用指南请务必阅读官方文档,你想要的都有)。
关于如何在centos7.5上安装mysql请看这篇:Centos7.5安装mysql5.7.23-二进制包方式安装-完美安装,一步到位
环境:
软件环境 | |
---|---|
虚拟机 | VMware Workstation Pro |
操作系统 | centos7.5 |
数据库 | mysql 5.7.23 |
虚拟化后的各服务器配置以及承担角色:
服务器名称 | IP地址 | 配置 | 角色 |
---|---|---|---|
master1 | 192.168.3.9 | 操作系统:centos7.5,CPU*1,内存:512M | 源数据库 1,与源数据库2互为主备 |
master2 | 192.168.3.10 | 操作系统:centos7.5,CPU*1,内存:512M | 源数据库 2,与源数据库1互为主备 |
slave1 | 192.168.3.11 | 操作系统:centos7.5,CPU*1,内存:512M | 从数据库1,为源数据库1的从数据库 |
slave2 | 192.168.3.12 | 操作系统:centos7.5,CPU*1,内存:512M | 从数据库2,为源数据库2的从数据库 |
我们将搭建一套双主双从的数据库同步结构,完成并测试mysql的主主复制,主从复制,级联复制等功能。数据库结构图:
# 可以在sql窗口输入
SET GLOBAL server_id = 1;
# 也可以在my.cnf(windows系统为my.ini)文件的[mysqld]栏下配置
[mysqld]
server-id=1
[mysqld]
server-id=1
#二进制日志文件名前缀
log-bin=mysql-bin
#需要记录日志的数据库,
binlog-do-db=test_db
# 如果需要记录多个,则配置多次本属性
# binlog-do-db=test_db1
# 不记录日志的数据库,同步时不会同步这些表的改动。
binlog-ignore-db=mysql
# 同理,如果需要记录多个,则配置多次本属性
binlog-ignore-db=sys
# 控制二进制文件刷盘的频率和时机
sync_binlog=1
innodb_flush_log_at_trx_commit=1
CREATE USER 'repl'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 12987 | test_db | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#把File下面的mysql-bin.000004和Position 下的12987记录下来备用(以实际显示为准)。
# 创建指定数据库test_db的数据备份
mysqldump -uroot -p --databases test_db --master-data > /home/test_db.sql
# 用scp远程拷贝至从服务器
scp /home/test_db.sql [email protected]:/home
scp /home/test_db.sql [email protected]:/home
scp /home/test_db.sql [email protected]:/home
[root@vm ~]# mysql -uroot -p
mysql> SHOW MASTER STATUS;
+------------------+-----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 723798548 | test_db | mysql | |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.02 sec)
#把File下面的mysql-bin.000002 和Position 下的723798548 记录下来备用(以实际显示为准)。
master1和master2关于主数据库的准备做完之后,我们就有两台mysql主服务器,分别是192.168.3.9(server-id=1)和192.168.3.10(server-id=2),现在我们开始配置从数据库。从数据库的配置除了server-id以及对应的主服务器的Ip不一样,其它基本一致。
[mysqld]
server-id=1
由于master1既作为master2和slave1主数据库,又作为master2的从数据库,因此我们希望master2的更改也能同步至slave1,这就需要打开mysql的同步数据记录至binlog的功能(默认是不记录的)
log_slave_updates=1。
#这里贴上master1完整的my.cnf配置文件,master2的配置文件只需要修改一下server-id即可。
[mysqld]
port=3306
# ---------------------数据同步相关配置开始
server-id=1
#二进制日志文件名前缀
log-bin=mysql-bin
#需要记录日志的数据库,
binlog-do-db=test_db
# 如果需要记录多个,则配置多次本属性
# binlog-do-db=test_db1
# 不记录日志的数据库,同步时不会同步这些表的改动。
binlog-ignore-db=mysql
# 同理,如果需要记录多个,则配置多次本属性
binlog-ignore-db=sys
# 控制二进制文件刷盘的频率和时机
sync_binlog=1
innodb_flush_log_at_trx_commit=1
#打开同步数据日志记录
log_slave_updates=1
# ---------------------数据同步相关配置结束
character-set-server=utf8
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
#innodb_buffer_pool_size=8M
[mysqld_safe]
log-error=/usr/local/mysql/data/error.log
pid-file=/usr/local/mysql/data/mysql.pid
tmpdir = /tmp
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
# master1的主服务为master2,因此
# MASTER_HOST='192.168.13.10',
# MASTER_LOG_FILE为master2的File:mysql-bin.000002,
# MASTER_LOG_POS为master2的Position:723798548
CHANGE MASTER TO MASTER_HOST='192.168.13.10', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=723798548;
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event #说明IO线程已启动并且等待主数据库发送文件
Master_Host: 192.168.13.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 723798548
Relay_Log_File: vm-relay-bin.000002
Relay_Log_Pos: 591
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes #说明IO线程已启动
Slave_SQL_Running: Yes #说明SQL执行线程已启动
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 723798548
Relay_Log_Space: 795
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
#当前同步数据同主数据的数据时间延时(单位秒),也就是说当前数据版本落后主数据库多少秒
#通过这个参数可以大概了解到从数据库的数据同步效率,从而针对性的改造业务系统的读取延时或者缓存时间等,从而降低主从同步数据不一致造成的影响。
#关于如何保持主从数据一致,这又是下一个话题了。
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
# 最新的失败日志,IO和SQL执行的都会显示出来
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
#注意这个UUID,有些数据库无法同步就是因为是直接完整复制的源数据库文件,导致UUID没有更改。
# 如果出现UUID相同的情况,删除从数据库的auto.cnf文件再重启数据库即可。
Master_UUID: ad85daaa-dd26-11ea-93e5-000c29c3c030
Master_Info_File: /usr/local/mysql/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.02 sec)
[mysqld]
server-id=2
log_slave_updates=1。
数据恢复
master2在作为主数据库的时候已经从master1恢复了数据。
配置主服务器地址和账户信息
# master2的主服务为master1,因此
# MASTER_HOST='192.168.13.9',
# MASTER_LOG_FILE为master2的File:mysql-bin.000004,
# MASTER_LOG_POS为master2的Position:12987
CHANGE MASTER TO MASTER_HOST='192.168.13.9', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=12987 ;
mysql> START SLAVE;
#这里贴上slave1完整的my.cnf配置文件,slave2的配置文件只需要修改一下server-id即可。
[mysqld]
port=3306
# ---------------------数据同步相关配置开始
server-id=3
# ---------------------数据同步相关配置结束
character-set-server=utf8
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
#innodb_buffer_pool_size=8M
[mysqld_safe]
log-error=/usr/local/mysql/data/error.log
pid-file=/usr/local/mysql/data/mysql.pid
tmpdir = /tmp
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[root@vm ~]# mysql -uroot -p
# slave1的主服务为master1,因此
# MASTER_HOST='192.168.13.9',
# MASTER_LOG_FILE为master2的File:mysql-bin.000004,
# MASTER_LOG_POS为master2的Position:12987
CHANGE MASTER TO MASTER_HOST='192.168.13.9', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=12987;
mysql> START SLAVE;
[mysqld]
server-id=4
[root@vm ~]# mysql -uroot -p
# slave2的主服务为master2,因此
# MASTER_HOST='192.168.13.10',
# MASTER_LOG_FILE为master2的File:mysql-bin.000002,
# MASTER_LOG_POS为master2的Position:723798548
CHANGE MASTER TO MASTER_HOST='192.168.13.10', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=723798548;
mysql> START SLAVE;
Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
这个错误的大概意思就是IO线程停止运行,因为主数据库和从数据库的UUID相同,mysql的主从数据库的UUID必须不相同才能执行同步任务。
那么,UUID是个啥玩意呢?为啥我们明明配置了不同的server-id,咋还整了个UUID相同的异常出来了呢?详情请见:官方文档-service_id。
那么如何解决这个问题呢?如官方文档所描述的,
- Attempt to read and use the UUID written in the file data_dir/auto.cnf (where data_dir is the server’s data directory).
- If data_dir/auto.cnf is not found, generate a new UUID and save it to this file, creating the file if necessary.
UUID是自动生成的,写在data_dir/auto.cnf这个文件里面的,并且我们不能尝试去修改或者写入这个文件。但是当文件不存在的时候,mysql会生成一个新的UUID并将其保存在这个文件中。所以,我们可以删除这个文件,对,就是数据目录下的auto.cnf,删掉重启就完事了。
我们本次的数据目录是:/usr/local/mysql/data/
[root@vm ~]# ls /usr/local/mysql/data/
auto.cnf ib_buffer_pool ib_logfile0 ibtmp1 mysql mysql-bin.000002 mysql.pid relay-log.info sys vm-relay-bin.000002
error.log ibdata1 ib_logfile1 master.info mysql-bin.000001 mysql-bin.index performance_schema ry_city vm-relay-bin.000001 vm-relay-bin.index
删掉auto.cnf,然后重启。
mysql> SHOW SLAVE STATUS\G;
......
......
ERROR:
No query specified
原因是在执行命令:SHOW SLAVE STATUS\G;的时候,多加了一个“;”分号。执行:SHOW SLAVE STATUS\G 就没事了。
Error 'Operation RENAME USER failed for 'test13'@'%'' on query. Default database: 'test_db'. Query: 'RENAME USER `test13`@`%` TO `test11`@`%`'
Error 'Operation CREATE USER failed for 'test333'@'%'' on query. Default database: 'test_db'. Query: 'CREATE USER 'test333'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9''
参考: 多源复制遇到CREATE USER FAILED错误 ,同内容文章很多,貌似大家转载引用的时候都不写来源的,所以不确定哪一篇是原创哈,先引一篇看起来像的。
文章大意为:
在多于源数据同步的时候,从数据库上报出了创建用户失败的日志。
MySQL Multi-Source Replication enables a replication slave to receive transactions from multiple sources simultaneously. Multi-source replication does not implement any conflict detection or resolution when applying the transactions, and those tasks are left to the application if required.
在应用事务时,多源复制不会实现任何冲突检测或解决方案,并且如果需要,这些任务将留给应用程序。
首先怀疑是配置了binlog_format=‘STATEMENT’,因为如果是基于行复制(row)的时候从数据库会检查数据所属数据库,如果不在二进制日志所配置的库列表中(通过binlog-do-db、
binlog-ignore-db、eplicate_db和replicate_ignore_db进行配置),则会忽略更改(5.7版本默认是基于行复制)。但是经测试,基于行的复制一样会出现上述错误信息。
Only DML statements can be logged using the row format. DDL statements are always logged as statements, even when binlog_format=ROW. All DDL statements are therefore always filtered according to the rules for statement-based replication. This means that you must select the default database explicitly with a USE statement in order for a DDL statement to be applied.
只能使用行格式记录DML语句。DDL语句始终作为语句记录,即使在binlog_format=ROW时也是如此。因此,所有DDL语句都会通过过滤规则。这意味着您必须使用use语句显式选择默认数据库,才能应用DDL语句。
也就是说明,当我们操作DDL/DCL语句时,必须显示的指定数据库。例如 use mysql,如果不显示地指定数据库,则语句会被同步,一旦从数据库中有重名用户或者其它情况事务执行不成功,就会出现上述错误,并且同步失败。至于什么时候需要指定,哪些语句行复制规则不会过滤,请看:基于语句复制和基于行复制的优缺点
终于有空写写文章了,可以把以前的笔记都整理整理发出来。下次我们有空讨论下主从数据一致性问题?