MySQL数据库的主从同步实现及应用

时间:2023-03-08 17:29:27
MySQL数据库的主从同步实现及应用

>>主从同步机制及应用

读写分离(Read/Write Splitting)让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),从数据库处理SELECT查询操作,
在大规模高并发的系统中,读写分离是提高性能很重要的手段。
读写分离实现的基础就是MySQL的主从同步,因此对于主从同步的管理也就显得非常重要。

(1)MYSQL主从同步的作用

1.数据分布
2.负载平衡(load balancing)
3.备份(Copy)
4.高可用性(high availability)和容错

(2)主从同步的详细过程如下:

1. 主服务器验证连接。
2. 主服务器为从服务器开启一个线程。
3. 从服务器将主服务器日志的偏移位告诉主服务器。
4. 主服务器检查该值是否小于当前二进制日志偏移位。
5. 如果小于,则通知从服务器来取数据。
6. 从服务器持续从主服务器取数据,直至取完,这时,从服务器线程进入睡眠,主服务器线程同时进入睡眠。
7. 当主服务器有更新时,主服务器线程被激活,并将二进制日志推送给从服务器,并通知从服务器线程进入工作状态。
8. 从服务器SQL线程执行二进制日志,随后进入睡眠状态。

>>MySQL主从同步的搭建过程

简单学习一个典型的MySQL主从同步的搭建过程,内容参考自论坛。

(1)主从同步环境介绍

操作系统环境:Centos 64 bit
MYSQL版本:MYSQL 5.1
主服务器的IP:192.168.106.1
从服务器的IP:192.168.106.2

(2)在主服务器上建立同步帐号

在设置权限的时候不要将密码设置过于简单:

GRANT REPLICATION SLAVE,FILE ON *.* TO 'replication'@'192.168.106.%' IDENTIFIED BY 'mysqlpassword';
FLUSH PRIVILEGES;

  

(3)从服务器配置文件的更改

server-id = 2
replicate-wild-ignore-table=mysql.%
log-slave-updates #这个有需要可以开启

注意:

1. server-id这一项需要认真检查,一定不能和主服务器冲突了,不然到时候会出现莫名其妙的问题,因为同步的时候会会根据server-id做判断,如果server-id一样就不进行同步了,不然可能会导致死循环(主主同步或者环状同步的时候)。

2.这里要使用replicate-wild-ignore-table参数,而不是用replicate-do-db或者replicate-ignore-db来过滤需要同步的数据库和不需要同步的数据库。
几个原因:
replicate-wild-ignore-table参数能同步所有跨数据库的更新,比如replicate-do-db或者replicate-ignore-db不会同步类似

use mysql;
UPDATE test.aaa SET amount=amount+10;

replicate-wild-ignore-table=mysql.%在以后需要添加同步数据库的时候能方便添加而不需要重新启动从服务器的数据库,因为以后很可能需要同步其他的数据库。

3.auto_increment_increment和auto_increment_offset参数,这两个参数一般用在主主同步中,用来错开自增值,防止键值冲突。

4.--slave-skip-errors参数,最好不要使用这些跳过错误的参数,当你使用这些参数时候,MYSQL会忽略那些错误,这样会导致你的主从服务器数据不一致。

(4)从主服务器得到一个快照版本

如果你的是MYISAM或者既有MYISAM又有INNODB的话就在主服务器上使用如下命令导出服务器的一个快照:

mysqldump -uroot -p --lock-tables --events --triggers --routines --flush-logs --master-data=2 --databases test > db.sql

只有INNODB的话就是用如下命令:

mysqldump -uroot -p --single-transaction --events --triggers --routines --flush-logs --master-data=2 --databases test > db.sql

这里需要注意几个参数的使用:

--single-transaction 这个参数只对innodb适用。
--databases 后面跟除mysql以后的其他所有数据库的库名,我这里只有一个test库。
--master-data 参数会记录导出快照时候的mysql二进制日志位置,一会会用到。

(5)将快照版本还原到从服务器上

mysqldump -uroot -p -h 192.168.106.2 test < db.sql

将快照版本还原到从服务器上以后,此时从服务器上的数据和主服务器的数据是一致的。

(6)在从服务器上使用change master从主服务器上同步

使用grep命令查找到二进制日志的名称以及位置

# grep -i "change master" db.sql

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=106;

生成CHANGE MASTER语句,然后在从上执行

STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='192.168.106.1',MASTER_USER='replication',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=106;
START SLAVE;

(7)这样就完成了主从同步的搭建,最后使用

SHOW SLAVE STATUS;

查看Slave_IO_Running和Slave_SQL_Running的状态,如果都为Yes,就大功告成了。

注意不要将同步的信息写入配置文件中,不方便管理,尤其是有变动需要重启。

>>MYSQL主从同步的管理

这里介绍一些管理MYSQL主从同步的命令:

(1)停止MYSQL同步

STOP SLAVE IO_THREAD; #停止IO进程
STOP SLAVE SQL_THREAD; #停止SQL进程
STOP SLAVE; #停止IO和SQL进程

  

(2)启动MYSQL同步

START SLAVE IO_THREAD; #启动IO进程
START SLAVE SQL_THREAD; #启动SQL进程
START SLAVE; #启动IO和SQL进程

  

(3)重置MYSQL同步

RESET SLAVE;

用于让从属服务器忘记其在主服务器的二进制日志中的复制位置, 它会删除master.info和relay-log.info文件,以及所有的中继日志,并启动一个新的中继日志,当你不需要主从的时候可以在从上执行这个操作。不然以后还会同步,可能会覆盖掉你的数据库。

(4)查看MYSQL同步状态

SHOW SLAVE STATUS;

这个命令主要查看Slave_IO_Running、Slave_SQL_Running、Seconds_Behind_Master、Last_IO_Error、Last_SQL_Error这些值来监控复制的状态。

(5)临时跳过MYSQL同步错误

经常会出现mysql主从同步遇到错误的时候,比如一个主键冲突等,
那么就需要在确保那一行数据一致的情况下临时的跳过这个错误,使用命令:

SQL_SLAVE_SKIP_COUNTER = n,

n是表示跳过后面的n个事件,比如我跳过一个事件的操作如下:

STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;

  

(6)从指定位置重新同步

有的时候主从同步有问题了以后,需要从log位置的下一个位置进行同步,相当于跳过那个错误,
这时候也可以使用CHANGE MASTER命令来处理,只要找到对应的LOG位置就可以,比如:

CHANGE MASTER TO MASTER_HOST='192.168.106.1主库地址',
MASTER_USER='replication', MASTER_PASSWORD='mysqlpassword',
MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=106;
START SLAVE;

  

>>MYSQL主从同步的管理

不要乱使用SQL_SLAVE_SKIP_COUNTER命令。
这个命令跳过之后很可能会导致你的主从数据不一致,一定要先将指定的错误记录下来,然后再去检查数据是否一致,尤其是核心的业务数据。

使用replicate-wild-ignore-table选项而不要使用replicate-do-db或者replicate-ignore-db。
原因已经在上面做了说明。

将主服务器的日志模式调整成mixed。
每个表都加上主键,主键对数据库的同步会有影响尤其是居于ROW复制模式。

>>主从不同步的错误解决

(1)忽略错误后,继续同步

该方法适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况
解决:

stop slave; 
#表示跳过一步错误,后面的数字可变 
set global sql_slave_skip_counter =1; 
start slave; 
之后再用mysql> show slave status\G 查看: 
Slave_IO_Running: Yes 
Slave_SQL_Running: Yes 
ok,现在主从同步状态正常。

(2)重新做主从,完全同步

该方法适用于主从库数据相差较大,或者要求数据完全统一的情况
解决步骤如下:

1.先进入主库,进行锁表,防止数据写入 
使用命令: 
mysql> flush tables with read lock; 
注意:该处是锁定为只读状态,语句不区分大小写

2.进行数据备份 
#把数据备份到mysql.bak.sql文件 
[root@server01 mysql]#mysqldump -uroot -p -hlocalhost > mysql.bak.sql 
这里注意一点:数据库备份一定要定期进行,可以用shell脚本或者python脚本,都比较方便,确保数据万无一失。

3.查看master 状态

mysql> show master status;

+-------------------+----------+--------------+-------------------------------+ 
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | 
+-------------------+----------+--------------+-------------------------------+ 
| mysqld-bin.000001 | 3260 | | mysql,test,information_schema | 
+-------------------+----------+--------------+-------------------------------+ 
1 row in set (0.00 sec)

4.把mysql备份文件传到从库机器,进行数据恢复

#使用scp命令 
[root@server01 mysql]# scp mysql.bak.sql root@192.168.128.101:/tmp/

5.停止从库的状态 
mysql> stop slave;

6.然后到从库执行mysql命令,导入数据备份 
mysql> source /tmp/mysql.bak.sql

7.设置从库同步,注意该处的同步点,就是主库show master status信息里的| File| Position两项 
change master to master_host = '192.168.128.100', master_user = 'rsync', master_port=3306, master_password='', master_log_file = 'mysqld-bin.000001', master_log_pos=3260;

8.重新开启从同步 
mysql> stop slave;

9.查看同步状态 
mysql> show slave status\G 查看: 
Slave_IO_Running: Yes 
Slave_SQL_Running: Yes

整理自:

MySQL主从同步机制及同步中的问题处理

mysql主从数据库不同步的2种解决方法