MySQL 5.7主从复制与主主复制实现细节分析
0.简介:
MySQL作为世界上使用最为广泛的数据库之一,免费是其原因之一。但不可忽略的是它本身的功能的确很强大。随着技术的发展,在实际的生产环境中,由单台MySQL数据库服务器不能满足实际的需求。此时数据库集群就很好的解决了这个问题了。采用MySQL分布式集群,能够搭建一个高并发、负载均衡的集群服务器(这篇博客暂时不涉及)。在此之前我们必须要保证每台MySQL服务器里的数据同步。数据同步我们可以通过MySQL内部配置就可以轻松完成,主要有主从复制和主主复制。
1.准备环境:
W8 mysql5.7 (192.168.2.115)
W7 mysql5.7 (192.168.2.138)
2.主从复制:
(0)原理
(1)确保两台电脑都有mysql服务器
log-bin=mysql-bin 开启二进制日志
注意:二进制日志必须开启,因为数据的同步实质上就是其他的MySQL数据库服务器将这个数据变更的二进制日志在本机上再执行一遍。
w8 为主数据库服务器
w7 为从数据库服务器
(2)配置文件
- 修改主服务器W8配置文件
一般Linux中的MySQL配置文件都在/etc/my.cnf(windows中的配置文件为mysql.ini或者my.ini)
log-bin=mysql-bin 开启二进制日志(主服务器配置)
注意:二进制日志必须开启,因为数据的同步实质上就是其他的MySQL数据库服务器将这个数据变更的二进制日志在本机上再执行一遍。
如下:
也可以指定日志格式,也可以不指定:
#指定日志格式
binlog-format=mixd/row/statement
- 重启Mysql服务:
或者:
- 修改从服务器W7的配置:(修改server-id,与主服务器不能相同,否则下面会报错)
(3)开始构建主从复制:
- 第一步: 在192.168.2.115中创建一个在192.168.2.138主机中可以登录的MySQL用户
W8创建账户:
GRANT ALL ON *.* TO root@'%' IDENTIFIED BY 'root' FLUSH PRIVILEGES
在W7电脑中连接并测试: (能连接则表示授权成功)
C:/>mysql -h 192.168.2.115 -P 3306 -u root -proot (注意第一个P大写)
- 第二部: 查看W8(主服务器)MySQL服务器二进制文件名与位置
mysql> SHOW MASTER STATUS;
- 第三步: 告知二进制文件名与位置
在192.168.2.138(从服务器)中执行:
CHANGE MASTER TO MASTER_HOST='192.168.2.115',MASTER_USER='root',MASTER_PASSWORD='root',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=586;
- 开始测试主从配置
在W7中开启主从复制:
START SLAVE; #开启复制,停止用stop slave;
查看主从复制是否配置成功
SHOW SLAVE STATUS; #查看主从复制是否配置成功
当看到Slave_IO_Running: YES、Slave_SQL_Running: YES才表明状态正常
说明:
Slave_IO_Running――此进程负责从Slave从Master上读取binlog日志,并写入Slave上的中继日志。
Slave_SQL_Running――此进程负责读取并执行中继日志中的binlog日志。
这两个进程的状态需全部为YES,只要有一个为NO,则复制就会停止。
当Slave中Relay_Master_Log_File和Master_Log_File相同且Read_Master_Log_Pos和Exec_Master_Log_Pos完全相同时,则表明Slave和Master处于完全同步的状态。
- 发现上面不正常,解决办法如下:(原因是上面忘记更换从服务器的server-id,如果从服务器更换了server-id应该没错)
第一步:查看mysql错误日志文件并查看错误日志:
SHOW VARIABLES LIKE '%error%'
第二步:查看日志
第三步:修改从服务器的server-id重新启动服务器后测试:
可以通过stop slave;之后查看err日志修改配置重启进行查看。
到这里主从复制配置就算完成了
(4).测试主从复制
第一步:测试DDL
- 主服务器(W8)创建库与表
主服务器创建一个database,名字为:masterdb,
并在主服务创建一个user表
CREATE TABLE `masterdb`.`user`( `id` VARCHAR(20) NOT NULL , `name` VARCHAR(20) , PRIMARY KEY (`id`) );
主服务器数据库较多:
- 从服务器查看数据库:
第二步:测试DML
(1)测试增加
- 主服务器插入两条数据:
- 从服务器查看数据:(也同步过来)
反过来:(看从服务器是否影响主服务器)
- 从服务先增加一条数据
- 主服务器还是两条
此时主服务器增加一条编号是3的数据(3在从服务器中已经存在)
从服务器报错并停止主从复制(主键冲突):
解决办法:删掉从服务器上数据并重新启动slave,start slave;
(2)测试修改:
- 主服务器修改
- 从服务器也跟着修改
总结:
主服务器增加数据,从服务器跟着增加数据。从服务器增加数据不会影响主服务器。如果主服务器增加的数据主键在从服务器上已经存在会因为主键冲突而停止slave线程。
主服务器修改数据,从服务器跟着修改数据,从服务器修改不会影响主服务器
主服务器删除数据,从服务器跟着删除数据,从服务器删除数据不会影响主服务器。
上面就达到了主从复制的效果,多个主从配置也是如此,剩余的问题就是使从服务器只能读取数据(只读状态)。参考我的另一篇博客:http://www.cnblogs.com/qlqwjy/p/8541959.html:
常用语句:
show master status ; 查看master的状态, 尤其是当前的日志及位置
show slave stattus; 查看slave的状态.
reset slave ; 重置slave状态.
start slave ; 启动slave 状态(开始监听msater的变化)
stop slave; 暂停slave状态;
主服务器的日志格式用哪种好?
有 statement,row, mixed3种,其中mixed是指前2种的混合.
以insert into xxtable values (x,y,z)为例,
影响: 1行,且为新增1行, 对于其他行没有影响.
这个情况,用row格式,直接复制磁盘上1行的新增变化.
以update xxtable set age=21 where name=’sss’;
这个情况,一般也只是影响1行. 用row也比较合适.
以过年发红包,全公司的人,都涨薪100元.
update xxtable set salary=salary+100;
这个语句带来的影响,是针对每一行的, 因此磁盘上很多row都发生了变化.
此处,适合就statment格式的日志.
2种日志,各有各的高效的地方,mysql提供了mixed类型.
可以根据语句的不同,而自动选择适合的日志格式.
3.主主复制
3.1实现原理
主主复制即在两台MySQL主机内都可以变更数据,而且另外一台主机也会做出相应的变更。聪明的你也许已经想到该怎么实现了。对,就是将两个主从复制有机合并起来就好了。只不过在配置的时候我们需要注意一些问题,例如,主键重复,server-id不能重复等等。
3.2配置文件
W8(主服务器)
server-id=11 #任意自然数n,只要保证两台MySQL主机不重复就可以了。
log-bin=mysql-bin #开启二进制日志
auto_increment_increment=2 #步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=1 #起始值。一般填第n台主MySQL。此时为第一台主MySQL
binlog-ignore=mysql #忽略mysql库【我一般都不写】
binlog-ignore=information_schema #忽略information_schema库【我一般都不写】
replicate-do-db=masterdb #要同步的数据库,默认所有库
Mysql5.7启动报错,无法识别的变量binlog-ignore,去掉之后正常启动
W7(从服务器)
server-id=2
log-bin=mysql-bin
auto_increment_increment=2
auto_increment_offset=2
replicate-do-db=aa
配置好后重启MySQL
3.3开始构建主主复制:
因为主主复制是两个主从复制组合一起,所以我就接着上面主从复制接着配置。
- 第一步:在W7中创建一个W8主机中可以登录的MySQL用户并测试
用户:w7
密码:w7
mysql>GRANT REPLICATION SLAVE ON *.* TO 'w7'@'%' IDENTIFIED BY 'w7';
mysql>FLUSH PRIVILEGES;
- 第二步:
在w7中查看二进制日志名和位置
mysql> show master status\G
*************************** 1. row *********
File: mysql-bin.000001
Position: 597
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
- 第三步:告知二进制文件名与位置
W8中执行:
CHANGE MASTER TO MASTER_HOST='192.168.2.138',MASTER_USER='w7',MASTER_PASSWORD='w7',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=597;
完成主主复制配置
3.4测试主主复制
分别开启start slave;
mysql>SHOW SLAVE STATUS\G #查看主从复制是否配置成功
W8中:
mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.2.138 Master_User: w7 Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 597 Relay_Log_File: root-relay-bin.000006 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: masterdb 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: 597 Relay_Log_Space: 526 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 Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 Master_UUID: d4f4161c-2447-11e8-9eed-047d7bf2e5cd Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\master .info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more up dates 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.00 sec) mysql>
当看到Slave_IO_Running: YES、Slave_SQL_Running: YES才表明状态正常
W7中执行:
mysql> start slave; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.2.115 Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 154 Relay_Log_File: GBXRNQQ5EF4WTGW-relay-bin.000011 Relay_Log_Pos: 367 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: masterdb 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: 154 Relay_Log_Space: 750 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 Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 11 Master_UUID: 04b999c4-b5dc-11e6-9143-f82fa8d3d350 Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\master .info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more up dates 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.00 sec)
当看到Slave_IO_Running: YES、Slave_SQL_Running: YES才表明状态正常
3.5实际数据测试主主复制:
(1)测试增加:
- W8中增加一条数据:
查看W7发现也跟着增加
- W7中增加一条数据
发现W8也跟着增加:
(2)测试修改:
发现修改W8影响W7,修改W7 也影响W8
(3)测试删除:
发现删除W8影响W7,删除W7 也影响W8
总结:
主主复制修改其中任意一台服务器另一台都会跟着变动,两个服务器相当于一个,可以实现同步。
当在从服务器stop slave;之后,修改主服务器不会影响从服务器。所以可以通过start slave与stop slave;开启主从与关闭复制。
Mysql主从复制及主主复制 参考https://www.cnblogs.com/phpstudy2015-6/p/6485819.html
出现:Slave_IO_Running: No 的解决办法参考 http://www.jb51.net/article/27220.htm
限制mysql为只读状态,参考: http://www.cnblogs.com/qlqwjy/p/8541959.html
mysql读写分离: 参考http://jayluns.iteye.com/blog/2275690