MySQL主从同步原理与实战

MySQL主从同步

1 MySQL的安装

关于MySQL的安装,可以在官网搜索教程或者在网上查找教程,也可以参考 Mysql 8.0.12解压版安装

具体配置就不一一介绍了。基本按照上面的链接可以搞定。如果不行的话,就是用户权限或者目录权限的一些问题,调整下即可。

2 MySQl主从同步实践

MySQL复制有两种方法:

  • 传统方式:基于主库的bin-log将日志事件和事件位置复制到从库,从库再加以 应用来达到主从同步的目的
  • Gtid方式:global transaction identifiers是基于事务来复制数据,因此也就不依赖日志文件位置,同时又能更好的保证主从库数据一致性

MySQL复制有多种类型:

  • 异步复制:一个主库,一个或多个从库,数据异步同步到从库
  • 同步复制:在MySQL Cluster中特有的复制方式
  • 半同步复制:在异步复制的基础上,确保任何一个主库上的事务在提交之前至 少有一个从库已经收到该事务并日志记录下来
  • 延迟复制:在异步复制的基础上,人为设定主库和从库的数据同步延迟时间,即保证数据延迟至少是这个参数

复制的工作原理是数据库修改事件记录到bin log中并传递到slave,然后slave在本地还原的过程。而事件记录到bin log的格式会有所不同。

MySQL复制有三种核心格式

  • 基于语句的复制(statement based replication):基于主库将SQL语句写入到 bin log中完成复制
  • 基于行数据的复制(row based replication):基于主库将每一个行数据变化的信息作为事件写入到bin log中完成日志
  • 混合复制(mixed based replication):上述两者的结合。默认情况下优先使用基于语句的复制,只有当部分语句如果基于语句复制不安全的情况下才会自动切换为基于行数据的复制

以下binlog方式的主从同步实战

2.1 主从同步配置

2.1.1 配置方式1

mysql-master /etc/my.cnf 的配置

# mysql主节点编号
[mysqld] 
server-id = 1 #Mysql服务的唯一编号 每个mysql服务Id需唯一
log-bin=mysql-bin # logbin的名字
binlog-do-db=test01 #需要同步的数据库的名字,多个时候重复此配置
binlog-do-db=test02
#binlog-ignore-db=test03 #不需要同步的数据库的名字,多个时候重复此配置
log-slave-updates=1 # log更新间隔
slave-skip-errors=1 # 是跳过错误,继续执行复制操作(可选)

mysql-slave /etc/my.cnf 的配置

[mysqld] 
#Mysql服务的唯一编号 每个mysql服务Id需唯一
server-id = 2
# read_only=1只读模式,可以限定普通用户进行数据修改的操作,但不会限定具有super权限的用户(如超级管理员root用户)的数据修改操作。
# 如果想保证super用户也不能写操作,就可以就需要执行给所有的表加读锁的命令 “flush tables with read lock;”
read_only = 1

2.1.2 配置方式2

mysql-master /etc/my.cnf 的配置

[mysqld] 
#Mysql服务的唯一编号 每个mysql服务Id需唯一
server-id = 1
log-bin=mysql-bin # logbin的名字

mysql-slave /etc/my.cnf 的配置

[mysqld] 
#Mysql服务的唯一编号 每个mysql服务Id需唯一
server-id = 2
# read_only=1只读模式,可以限定普通用户进行数据修改的操作,但不会限定具有super权限的用户(如超级管理员root用户)的数据修改操作。
# 如果想保证super用户也不能写操作,就可以就需要执行给所有的表加读锁的命令 “flush tables with read lock;”
read_only = 1
replicate-do-db=test01 #需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可
replicate-ignore-db=test03 #需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可

2.2 启动主从同步

1. 创建同步账号

在从库创建同步账号并授权

mysql>CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
mysql>GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';
mysql>FLUSH PRIVILEGES;

2. 查看 master同步状态

查看master同步状态,记录结果中的file文件名和Position值,在从库开启同步的设置时候需要使用

# 查看主节点状态
mysql>show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |     3693 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3. 开启slave同步

在从库上进行如下操作开启同步

# 停止正在进行的slave(如果有)
mysql>stop slave;
# 需要主机名,上面步骤的账户密码以及日志文件名字和位置(请根据实际情况自行修改)
mysql>change master to master_host='192.168.109.129', master_user='slave', master_password='123456', 
\ master_log_file='mysql-bin.000001', master_log_pos=3693;
# 启动
mysql>start slave;
# 查看状态验证是否成功
mysql>show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.128
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 3693
               Relay_Log_File: localhost-relay-bin.000005
                Relay_Log_Pos: 624
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes # 网络OK
            Slave_SQL_Running: Yes # SQL同步OK
              Replicate_Do_DB: test_rp
                ......其他就不复制了.....
1 row in set (0.00 sec)

注意:
如果遇到Slave_IO_Running/Slave_SQL_Running 为NO 的情况,一般原因可能有:

  • 1:机器网络不通
  • 2:配置项写错,例如ip,密码等
  • 3:防火墙问题
  • 4:my.cnf的server-id或者 auto.cnf里面的server-uuid 重复

2.3 主从同步的异常处理

#在Slave上查看 
mysql> show slave status\G 
Slave_IO_Running: Yes 
Slave_SQL_Running: No 
#可见是Slave不同步 

针对这类同步异常的情况,一般有以下两种方式解决

  • 方式1:跳过错误,继续执行后续同步
  • 方式2:dump主库数据,恢复到从库后,重新开始同步

方式1: 适合于主从数据相差不大,数据一致性要求不是特别严格的情况,允许跳过部分错误,继续进行。操作如下:

## 进入从库的mysql
mysql>stop slave; 
mysql>et global sql_slave_skip_counter =1; #表示跳过一步错误,后面的数字可变 
mysql>start slave; 
mysql>show slave status\G; #查看
Slave_IO_Running: Yes 
Slave_SQL_Running: Yes 

出现以上结果,表示主从同步状态正常了。。。

方式2: 适合主从数据相差比较大,数据一致性要求比较高。
实现思路就是先把主库写停止,然后dump数据,在从库恢复,恢复之后再重新开启主从同步

操作如下:

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

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

3.查看master 状态 
mysql> show master status; 
+-------------------+----------+--------------+-------------------------------+ 
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | 
+-------------------+----------+--------------+-------------------------------+ 
| mysqld-bin.000001 | 3260 | |  | 
+-------------------+----------+--------------+-------------------------------+ 
1 row in set (0.00 sec) 

4.把mysql备份文件传到从库机器,进行数据恢复 
#使用scp命令 
[root@server01 mysql]# scp mysql.bak.sql root@192.168.109.129:/tmp/ 

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

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

7.设置从库同步,注意该处的同步点,就是主库show master status信息里的| File| Position两项 
mysql>change master to master_host = '192.168.109.129', master_user = 'slave', master_port=3306, master_password='123456', 
\ 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做主从复制)

3 MySQl主从同步原理

mysql-master-slave.jpg
  1. 在master机器上的操作:

    当master上的数据发生变化时,该事件变化会按照顺序写入bin-log中。当slave链接到master的时候,master机器会为slave开启binlog dump线程。
    当master的binlog发生变化的时候,bin-log dump线程会通知slave,并将相应的binlog内容发送给slave。

  2. 在slave机器上操作:

    当主从同步开启的时候,slave上会创建两个线程:I\O线程。该线程连接到master机器,master机器上的binlog dump 线程会将binlog的内容发送给该I\O线程。
    该I/O线程接收到binlog内容后,再将内容写入到本地的relay log;sql线程。该线程读取到I/O线程写入的ralay log。并且根据relay log 的内容对slave数据库做相应的操作。


参考链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335