MySQL主从复制

Posted liang-io

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL主从复制相关的知识,希望对你有一定的参考价值。

引子:普通文件的数据同步

  1. NFS网络文件共享可以同步存储数据
  2. 定时任务或守护进程结合,rsync,scp
  3. inotify+rsync出发时实时数据同步
  4. ftp数据同步,
  5. ssh key+scp/rsync

mysql主从复制

mysql支持单向,双向,链式级联,实时,异步辅助,在复制过程中,一台服务器充当主服务器(Master),而一个或多个其他的服务器充当从服务器(Slave)。复制可以是单向,M=>S,也可以是双向M<=>M,当然也可以是多M环状同步,

技术分享图片

主从复制的应用场景

mysql主从辅助有利于数据库架构的健壮性,提升访问速度和易于维护管理

主从服务器互为备份

主从服务器架构的设置,可以大大加强数据库架构的健壮性,如;当主服务器出问题时,我们可以人工或自动切换到从服务器继续提供服务

主从服务器读写分离分担网站压力

主从服务器架构可以通过程序(java)或代理软件(mysql-proxy)对用户的请求实现读写分离,即通过从服务器上仅仅处理用户的select查询请求,降低用户查询相应时间及读写同时在主服务器带来的压力,对于更新的数据仍然交给主服务器处理,确保主服务器和从服务器保持实时同步

MySQL主从同步配置步骤

  1. 准备俩台数据库环境,或者单台多实例环境,能否正常启动和登陆
  2. 配置my.cnf文件,主库配置log-bin和server-id参数,从库配置server-id,不能和主库及其他从库一样,一般不开启从库log-bin功能,注意:配置参数后要重启生效
  3. 登陆主库增加用于从库连接主库同步的账户例如:rep,并授权replication slave同步的权限
  4. 登陆主库,整库锁表flush table With read lock (窗口关闭后即失效,超时参数到了也失效)然后show master  status查看binlog的位置状态
  5. 新开窗口,linux命令行备份或者导读 原有的数据库数据,并拷贝到从库所在的服务器目录(如果数据量很大,并且允许停机,可以停机打包而不同mysqldump)
  6. 解锁主库,unlock tables;
  7. 把主库导出的原有数据恢复到从库
  8. 根据 主库的show master status查看binlog的位置状态,在从库执行change master to。。。语句
  9. 从库开启同步开关,start slave
  10. 从库show slave statusG,检查同步状态,并在主库进行更新测试

实战操作

实战操作,确保 server-id 要不同,通常主ID要小于从ID。一定注意。

# 3306和3307分别代表2台机器

 1 # 打开log-bin,并使server-id不一样
 2 
 3 #vim /data/3306/my.cnf
 4 log-bin = /data/3306/mysql-bin
 5 server-id = 1
 6 #vim /data/3307/my.cnf
 7 log-bin = /data/3307/mysql-bin
 8 server-id = 3
 9 
10 #检查
11 112 [[email protected] ~]# egrep "log-bin|server-id" /data/3306/my.cnf 
13 log-bin = /data/3306/mysql-bin
14 server-id = 1
15 [[email protected] ~]# egrep "log-bin|server-id" /data/3307/my.cnf  
16 log-bin = /data/3307/mysql-bin
17 server-id = 3
18 219 [[email protected] ~]# mysql -uroot -p -S /data/3306/mysql.sock -e "show variables like ‘log_bin‘;"
20 Enter password: 
21 +-----------------------+--------+
22 | Variable_name | Value |
23 +-----------------------+--------+
24 | log_bin       | ON  |    # ON 为开始开启成功
25 +-----------------------+--------+

建立用于从库复制的账号rep

通常会创建一个用于主从复制的专用账户,不要忘记授权。

 1 # 主库授权,允许从库来连接我取日志
 2 [[email protected] ~]# mysql -uroot -p -S /data/3306/mysql.sock 
 3 Enter password:
 4 
 5 # 允许从库192.168.17网段连接,账号rep,密码nick。
 6 mysql> grant replication slave on *.* to rep@192.168.17.% identified by nick;
 7 Query OK, 0 rows affected (0.00 sec)
 8 mysql> flush privileges;
 9 Query OK, 0 rows affected (0.00 sec)
10 
11 # 检查创建的rep账号:
12 mysql> select user,host from mysql.user;
13 +--------+-----------------------------+
14 | user | host              |
15 +--------+------------------------------+
16 | root | 127.0.0.1          |
17 | rep  | 192.168.17.%     |
18 | root | localhost           |
19 | root | localhost.localdomain |
20 +--------+------------------------------+
21 7    rows in set (0.00 sec)

备份主库,及恢复到从库

把主库现有数据备份下来,再恢复到从库,此时两个主机的数据一致。

如果事先有数据的话,这不不能忘。

 1 1)    在主库上加锁,使只有只读权限。
 2 mysql> flush table with read lock;
 3 Query OK, 0 rows affected (0.00 sec)
 4 #5.15.5锁表命令略有不同。
 5 # 5.1锁表:flush tables with read lock;
 6 # 5.5锁表:flush table with read lock;
 7 
 8 2)    记住就是这个点备份的。
 9 mysql> show master status;
10 +---------------------------+-------------+-------------------+--------------------------+
11 | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
12 +----------------------------+------------+--------------------+-------------------------+
13 | mysql-bin.000013  |   410 |             |               |
14 +----------------------------+------------+--------------------+-------------------------+
15 1 row in set (0.00 sec)
16 
17 3)    克隆窗口,备份数据。
18 [[email protected] ~]# mysqldump -uroot -p -S /data/3306/mysql.sock -A -B --events --master-data=2|gzip >/opt/rep.sql.gz
19 Enter password:
20 参数:    -A:备份所有的
21 #看rep.sql.gz参数
22 vim /opt/rep.sql.gz
23 -- CHANGE MASTER TO MASTER_LOG_FILE=mysql-bin.000013, MASTER_LOG_POS=410;
24 
25 4)    查看master status;数值是否正常
26 mysql> show master status;
27 +--------------------------+------------+--------------------+-------------------------+
28 | File            | Position | Binlog_Do_DB | Binlog_Ignore_DB |
29 +--------------------------+------------+--------------------+--------------------------+
30 | mysql-bin.000013 |    410 |            |                |
31 +--------------------------+------------+--------------------+--------------------------+
32 1 row in set (0.00 sec)
33 
34 5)    解锁库
35 mysql> unlock tables;
36 Query OK, 0 rows affected (0.00 sec)
37 
38 6)    恢复到从库
39 [[email protected] ~]# gunzip < /opt/rep.sql.gz | mysql -uroot -p -S /data/3307/mysql.sock
40 Enter password:

配置从库及生效

更改从库和主库的连接参数,配置生效。检查就成功了!

 1 1)    进入从库。
 2 [[email protected] ~]# mysql -uroot -p -S /data/3307/mysql.sock 
 3 Enter password:
 4 
 5 2)    更改从属服务器用于与主服务器进行连接和通讯的参数。
 6 mysql> CHANGE MASTER TO
 7       MASTER_HOST=192.168.17.98,
 8       MASTER_PORT=3306,
 9       MASTER_USER=rep,
10       MASTER_PASSWORD=nick,
11       MASTER_LOG_FILE=mysql-bin.000013,
12       MASTER_LOG_POS=410;
13 Query OK, 0 rows affected (0.01 sec)
14 
15 3)    查看更改的参数。
16 [[email protected] ~]# cd /data/3307/data/
17 [[email protected] data]# cat master.info 
18 18
19 mysql-bin.000013
20 410
21 192.168.200.98
22 REP
23 nick
24 3306
25 60
26 0
27 0
28 1800.000
29 0
30 4)    生效!
31 mysql> start slave;
32 Query OK, 0 rows affected (0.01 sec)
33 
34 5)    检查下列参数,符合则正常!
35 mysql> show slave statusG
36 Relay_Master_Log_File: mysql-bin.000013
37              Slave_IO_Running: Yes        #取logo。
38             Slave_SQL_Running: Yes        #读relay-bin、logo,写数据。
39 Seconds_Behind_Master: 0        #落后主库的秒数。
40 
41 6)    查看relay-bin.logo。
42 [[email protected] 3307]# cd /data/3307
43 [[email protected] 3307]# ll
44 总用量 48
45 drwxr-xr-x. 9 mysql mysql  4096 11月 19 18:52 data
46 -rw-r--r--. 1 mysql mysql  1900 11月 19 11:45 my.cnf
47 -rwx------. 1 root  root   1307 11月 10 17:06 mysql
48 -rw-rw----. 1 mysql mysql     6 11月 19 11:00 mysqld.pid
49 -rw-r-----. 1 mysql mysql 15090 11月 19 18:49 mysql_nick3307.err
50 srwxrwxrwx. 1 mysql mysql     0 11月 19 11:00 mysql.sock
51 -rw-rw----. 1 mysql mysql   150 11月 19 18:49 relay-bin.000001
52 -rw-rw----. 1 mysql mysql   340 11月 19 18:52 relay-bin.000002
53 -rw-rw----. 1 mysql mysql    56 11月 19 18:49 relay-bin.index
54 -rw-rw----. 1 mysql mysql    53 11月 19 18:52 relay-log.info
55 
56 7)查看relay-log.info。
57 [[email protected] 3307]# cat relay-log.info 
58 /data/3307/relay-bin.000002
59 340
60 mysql-bin.000013
61 497
62 8)查看master.info。
63 [[email protected] 3307]# cat data/master.info 
64 18
65 mysql-bin.000013
66 497
67 192.168.17.98
68 rep
69 nick
70 3306
71 60
72 0
73 0
74 1800.000
75 0

读写分离

读写分离在生产环境比比皆是,也是必备技能。

忽略MySQL主从复制授权表同步,读写分离

 1 1 [[email protected] 3306]# vim my.cnf
 2 2 #添加以下四行
 3 3 replicate-ignore-db = mysql
 4 4 binlog-ignore-db = mysql
 5 5 binlog-ignore-db = performance_schema
 6 6 binlog-ignore-db = information_schema
 7 7 
 8 8 server-id = 1
 9 1)通过read-only参数防止数据写入从库的方法。
10 #修改配置文件。
11 vim /data/3307/my.cnf
12 [mysqld]
13 read-only
14 #对用户授权事不能指定有super或all privileges权限。不然没效果。
15 #创建账户suoning,并刷新权限。
16 mysql> grant select,insert,update,delete on *.* to suoning@localhost identified by 123;
17 Query OK, 0 rows affected (0.00 sec)
18 mysql> flush privileges;
19 Query OK, 0 rows affected (0.00 sec)
20 #用创建账户登录,并创建库
21 [[email protected] 3307]# mysql -usuoning -p123 -S /data/3307/mysql.sock
22 mysql> create user [email protected]192.% identified by old123;
23 ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
24 
25 2)主从同步故障
26 A.    Last_SQL_Errno: 1007
27 stop slave;
28 set global sql_slave_skip_counter = 1;
29 start slave;
30 B.    忽略
31 skip-name-resolve        #忽略名字解析
32 slave-skip-errors = 1032,1062,1007    #忽略故障编号
33 
34 server-id = 3
35 
36 3)从库开启bin-log
37 vim my.cnf
38 log-bin = /data/3307/mysql-bin
39 log-slave-updates           #表示从库记录bin-log
40 expire_logs_days = 7        #保留7天bin-log。

主宕机

我们来模拟一下,如果主机宕机了,那我们该如何让从快速替换,让损失降到最小?当然了,双机热备也是一个不错的选择,一主多从的环境下,如果主宕机了,选一台从做主,继续和其它从同步。

 1 A.    查看每个从库的master.info,看谁的更靠前,最新,更大,丢的数据最少。
 2 [[email protected] 3307]# cat /data/3307/data/master.info 
 3 mysql-bin.000015
 4 326
 5 
 6 B.    确保所有relay log全部更新完毕。
 7 在每个从库上执行stop slave io_thread;show processlist;
 8 知道看到Has read all relay log;表示从库更新都执行完毕。
 9 
10 C.    登陆mysql -uroot -p -S /data/3307/mysql.sock
11 stop slave;
12 reset master;
13 quit
14 
15 D.    进入到数据库目录,删除master.info relay-log.info
16 cd /data/3307/data/
17 rm -f master.info relay-log.info
18 
19 E.    3307提升为主库
20 vim /data/3307/my.cnf
21 开启log-bin = /data/3307/mysql-bin
22 如存在log-slave-updates,read-only等一定要注释。
23 /data/3307/mysql restart
24 
25 F.    其它从库操作
26 stop slave;
27 change master to master_host =192.168.17.98;
28 start slave;
29 show slave statusG

双主

使用主主前提:表的主键自增。

 1 [[email protected] 3307]# vim my.cnf
 2 [mysqld]
 3 auto_increment_increment        = 2
 4 auto_increment_offset           = 2
 5 [[email protected] 3307]# ./mysql restart
 6 
 7 [[email protected] 3306]# vim my.cnf
 8 [mysqld]
 9 auto_increment_increment        = 2
10 auto_increment_offset           = 1
11 log-bin = /data/3306/mysql-bin
12 log-slave-updates
13 [[email protected] 3306]# ./mysql restart
14 
15 [[email protected] 3306]# mysqldump -uroot -pnick -S /data/3307/mysql.sock -A -B --master-data=1 -x --events > /opt/3307bak.sql
16 [[email protected] 3306]# mysql -uroot -pnick -S /data/3306/mysql.sock < /opt/3307bak.sql
17 
18 mysql> CHANGE MASTER TO
19       MASTER_HOST=192.168.17.98,
20       MASTER_PORT=3307,
21       MASTER_USER=rep,
22       MASTER_PASSWORD=nick;
23 mysql> start slave;
24 Query OK, 0 rows affected (0.00 sec)
25 mysql> show slave status G

MySQL备份及恢复

备份单个数据库

最基础的备份单个数据库,语法:mysqldump –u 用户名 –p 数据库名> 备份的数据库名

 1 备份nick_defailt数据库,查看内容。
 2 [[email protected] ~]# mysqldump -uroot -p -B nick_defailt >/opt/mysql_nick_defailt.bak
 3 Enter password: 
 4 [[email protected] ~]# egrep -v "#|*|--|^$" /opt/mysql_nick_defailt.bak 
 5 DROP TABLE IF EXISTS `oldsuo`;
 6 CREATE TABLE `oldsuo` (
 7   `id` int(4) NOT NULL,
 8   `name` char(20) NOT NULL,
 9   `age` tinyint(2) NOT NULL DEFAULT 0,
10   `dept` varchar(16) DEFAULT NULL
11 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
12 LOCK TABLES `oldsuo` WRITE;
13 INSERT INTO `oldsuo` VALUES (2,索�,0,NULL),(3,索尼,0,NULL),(4,底底,0,NULL);
14 UNLOCK TABLES;
15 DROP TABLE IF EXISTS `student`;
16 CREATE TABLE `student` (
17   `qq` varchar(15) DEFAULT NULL,
18   `id` int(4) NOT NULL AUTO_INCREMENT,
19   `name` char(20) NOT NULL,
20   `suo` int(4) DEFAULT NULL,
21   `age` tinyint(2) NOT NULL DEFAULT 0,
22   `dept` varchar(16) DEFAULT NULL,
23   `sex` char(4) DEFAULT NULL,
24   PRIMARY KEY (`id`),
25   KEY `index_name` (`name`)
26 ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
27 LOCK TABLES `student` WRITE;
28 INSERT INTO `student` VALUES (NULL,2,oldsuo,NULL,0,NULL,NULL),
29 (NULL,3,kangknag,NULL,0,NULL,NULL),
30 (NULL,4,kangkang,NULL,0,NULL,NULL),
31 (NULL,5,oldsuo,NULL,0,NULL,NULL),
32 (NULL,6,kangknag,NULL,0,NULL,NULL),
33 (NULL,7,kangkang,NULL,0,NULL,NULL);
34  UNLOCK TABLES;
35 
36 启用压缩备份数据库
37 [[email protected]~]#mysqldump -uroot -p -B nick_defailt|gzip>/opt/mysql_nick_defailt.bak.gz
38 Enter password: 
39 
40 恢复nick_defailt数据库
41 [[email protected] ~]# mysql -uroot -p nick_defailt </opt/mysql_nick_defailt.bak 
42 Enter password:
43 #加-B恢复方法
44 [[email protected] ~]#  mysql -uroot -p  </opt/mysql_nick_defailt_B.bak               
45 Enter password:
总结
1,备份用-B参数。增加use db,和create database的信息。
2,用gzip对备份的数据压缩。

备份多个数据库

备份多个数据库的情况呢?

1 #多个数据库名中间加空格
2 [[email protected] ~]# mysqldump -uroot -p -B nick_defailt oldsuo oldsuo_1|gzip>/opt/mul.sql.gz
3 Enter password:

备份单个及多个表

那如果备份单个和多个表,怎么办?

1 语法:mysqldump -u 用户名 -p 数据库名 表名 > 备份的文件名
2 [[email protected] ~]# mysqldump -uroot -p nick_defailt student >/opt/mysql_nick_defailt_student.bak
3 Enter password:
4 
5 语法:mysqldump -u 用户名 -p 数据库名 表名1  表名2  > 备份的文件名
6 [[email protected] ~]# mysqldump -uroot -p  nick_defailt student oldsuo >/opt/mysql_nick_defailt.bak        
7 Enter password:

mysqldump 的参数

mysqldump 的关键参数

-B指定多个库,增加建库语句和use语句。
--compact去掉注释,适合调试输出,生产不用。
-A 备份所有库。
-F刷新binlog日志。
--master-data 增加binlog日志文件名及对应的位置点。
-x,--lock-all-tables 
-l,--locktables
-d 只备份表结构
-t 只备份数据
--single-transaction 适合innodb事务数据库备份。

增量恢复

重要的来了,生产环境一般是增量备份与恢复;

所谓增量,就是在原数据的基础上继续添加数据,不必每次都重新添加,省时省力。

A:增量恢复必备条件:

1 开启MySQL数据库log-bin参数记录binlog日志。
2 [[email protected] 3306]# grep log-bin /data/3306/my.cnf 
3 log-bin = /data/3306/mysql-bin
4 存在数据库全备。

B:生产环境 mysqldump备份命令:

1 # 进行数据库全备,(生产环境还通过定时任务每日凌晨执行)
2 mysqldump -uroot -pnick -S /data/3306/mysql.sock --default-character-set=gbk --single-transaction -F -B nick |gzip >/server/backup/mysql_$(date +%F).sql.gz
3 # innodb引擎备份
4 mysqldump -u$MYUSER -p$MYPASS -S $MYSOCK -F --single-transaction -A -B |gzip >$DATA_FILE
5 # myisam引擎备份
6 mysqldump -u$MYUSER -p$MYPASS -S $MYSOCK -F -A -B --lock-all-tables |gzip >$DATA_FILE

C:恢复:

 1 # 通过防火墙禁止web等应用向主库写数据或者锁表。让主库暂时停止更新,然后再进行恢复。
 2 # 误操作删除nick库!
 3 
 4 1.    检查全备及binlog日志
 5 [[email protected] 3306]# cd /server/backup/
 6 [[email protected] backup]# gzip -d mysql_2018-11-17.sql.gz 
 7 [[email protected] backup]# vim mysql_2018-11-17.sql
 8 [[email protected] backup]# grep -i "change" mysql_2018-11-17.sql
 9 
10 2.    立即刷新并备份出binlog
11 [[email protected] 3306]# mysqladmin -uroot -pnick -S /data/3306/mysql.sock flush-logs
12 [[email protected] 3306]# cp /data/3306/mysql-bin.000030 /server/backup/
13 #误操作log-bin,倒数第二
14 [[email protected] backup]# mysqlbinlog -d nick mysql-bin.000030 >bin.sql    #导出为.sql格式。
15 [[email protected] backup]# vim bin.sql
16 找到语句drop database nick删除!!!(误操作语句)
17 
18 3.    恢复
19 [[email protected] backup]# mysql -uroot -pnick -S /data/3306/mysql.sock <mysql_2018-11-18.sql        #恢复之前的数据库全备
20 [[email protected] backup]# mysql -uroot -pnick -S /data/3306/mysql.sock nick < bin.sql
21 #恢复删除误操作语言的bin-log。

 

以上是关于MySQL主从复制的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 主从复制与读写分离(原理深刻,过程详细,值得一看)

MySQL主从复制与读写分离

MySQL主从复制及读写分离实际部署与验证

MySQL主从复制及读写分离实际部署与验证

mysql实现主从复制/主从同步

MySQL主从复制以及读写分离(❤❤❤❤含理论和实验❤❤❤❤大家中秋快乐!㊗)