比起Oracle的高可用方案,MySQL自带的主从同步高可用方案可谓非常简单。不需要复杂的设置,即可完成两台数据库服务器的主动复制,如果有需要,也可以实现主主复制。不过要特别提醒一下,主主复制没啥难度,但是要在生产系统实现实时热切换可没这么简单,这涉及到写数据安全的问题,以后有时间可以就这个问题展开讨论。以下配置在 MySQL 5.6 版本上成功运行。
常用命令
1
2
3
4
5
6
7
8
9
10
11
12
|
show master status;
show slave status\G;
stop slave;
start slave;
reset slave;
reset slave all; -- 删掉当前的slave配置
show variables like '%locks%';
show binlog events; -- 默认显示第一个binlog的内容
show binlog events in 'mysql-bin.000001'; -- 指定binlog
|
MySQL常用的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# /etc/my.cnf for mysql 5.6.x
# add by cd.net on 2022-01-11
# ---------------------------------
[mysqld]
datadir = /home/dbcenter/mysql-server
# 最好加上这个,否则连接会巨慢无比,大量超时待认证的连接
skip_name_resolve
skip_host_cache
max_connections = 500
max_connect_errors = 500
innodb_buffer_pool_size = 32G
# mysql 8.x 以上不能有下面这句
innodb_file_format = Barracuda
innodb_file_per_table = ON
performance_schema = OFF
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
join_buffer_size = 6G
sort_buffer_size = 4G
read_rnd_buffer_size = 1G
# 允许接收的数据包最大值
max_allowed_packet = 128M
# query slow
long_query_time = 1
slow-query-log = 1
slow-query-log-file = /home/dbcenter/mysql-server/query-slow.log
# replication +++++++++++++++++++++++++++++++++++++
# 不同服务器的server-id一定不能一样
server-id = 1158
# 开启binlog日志
log_bin = mysql-bin
binlog_format = mixed
# 忽略几个mysql自带的DB变动日志
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
# 同时也不复制这些表
replicate_wild_ignore_table = mysql.%
replicate_wild_ignore_table = information_schema.%
replicate_wild_ignore_table = performance_schema.%
# 这里的参数根据需要调节,控制MySQL高可用安全级别,根据业务特定在性能和数据一致性方面做决策
# InnoDB在复制中最大的持久性和一致性,[每次commit都 write cache & flush disk]
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
# 事务日志文件大小
innodb_log_file_size = 512M
[mysqld_multi]
mysqld = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
log = /var/log/mysqld_multi.log
!includedir /etc/my.cnf.d
|
MySQL主从同步和主主同步的要点就是两台服务器的配置文件差不多一样,差异是server-id
不一样。
下面介绍主要的配置步骤:(假设主服务器是A-IP,从服务器是B-IP)
第一步:配置主服务器A
1
2
3
|
-- 在主A-IP上面给从B-IP加一个访问用户并设置密码
grant replication slave,replication client on *.* to hot_backup@'B-IP' identified by 'you_password';
flush privileges;
|
注意:
1
2
3
4
|
# 如果是 mysql 8.0 以上版本,创建用户和授权必须分开设置。后面从服务器的设置同理。
create user hot@'B-IP' identified by 'xxx';
grant replication slave,replication client on *.* to hot@'B-IP' with grant option;
flush privileges;
|
第二步:配置从服务器B
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-- 在从B-IP也加入主A-IP用的账号(目前这个没有使用,主主模式会用到)
grant replication slave,replication client on *.* to hot_backup@'A-IP' identified by 'you_password';
flush privileges;
-- 在从B-IP上加一个账号,让主A-IP能访问,将数据备份推送到从B-IP服务器。(备份数据的过程还有其他方式)
grant all privileges on *.* to root_dump@'A-IP' identified by 'your_password';
flush privileges;
-- 删除从B上所有的binlog历史日志(为将来主主同步做准备)
reset master;
show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 120 | | mysql |
+------------------+----------+--------------+------------------+
|
第三步:主A的当前数据还原到从B
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
-- 登录主A做如下的配置,清空当前的binlog
reset master;
-- 锁住主A数据库,不让数据继续写入:
flush tables with read lock;
-- 查看当前主A的日志状态
show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 924 | | mysql |
+------------------+----------+--------------+------------------+
-- 一定要记住这里日志的位置,将作为从B同步数据的起点。
-- 接下来将主A当前数据快照,推送到从B(把想要备份的数据库都推送一遍)
mysqldump dbname1 -uroot -plocalpassword --opt | mysql dbname1 -uroot_dump -pyour_password -h B-IP
mysqldump dbname2 -uroot -plocalpassword --opt | mysql dbname2 -uroot_dump -pyour_password -h B-IP
...
-- 可以指定库中单独的一张或多张表名
mysqldump dbname table1 table2 -uroot -ppass --opt | mysql dbname -uroot_dump -ppass -h B-IP
-- 将所有的DB都推送给从B之后,到主A命令行解除写锁:
unlock tables;
|
第四步:从服务器B启动同步
1
2
3
4
5
6
7
8
|
-- 从B上登录mysql,给从B指定主服务器A
CHANGE MASTER TO MASTER_HOST='A-IP',MASTER_USER='hot_backup',MASTER_PASSWORD='you_password',
MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=924;
-- 启动同步
start slave;
-- 可以在从服务上查看当前同步状态
show slave status\G
|
查看从服务器的状态就会看到类似下图的结果:
看到Slave_IO_running 和 Slave_SQL_Running 的值都是 Yes,代表同步一切正常。恭喜MySQL的主从同步就完成了,更多状态的含义可以上网查找资料。
大家发现没有,虽然我们说的是主从同步,而实际主主同步很容易实现。因为我们在第二步第一条SQL语句已经在从服务器B中加入了主服务器A的访问授权,主服务器A也能抽取得到从服务器B的binlog日志文件,这样任何对从B的修改也可以同步到主A并还原。于是可以有下面第五步。
第五步:主A上启动对B的同步
1
2
3
4
5
6
7
8
9
|
-- 从A上登录mysql,给A指定主服务器B
CHANGE MASTER TO MASTER_HOST='B-IP',MASTER_USER='hot_backup',MASTER_PASSWORD='you_password',
MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=120;
-- 这里的120就是服务器B在reset master;之后,当时binlog日志文件的编号和对应字节位置。
-- 启动同步
start slave;
-- 可以在A上查看当前同步状态
show slave status\G
|
到这里主主同步就完成了,是不是很简单?我们就是需要这样简单的配置就能自动实现高级功能的工具,Oracle的高可用,主从复制方案就显得格外复杂,为啥搞的这么复杂显得自己NB吗?就怕是为了商业上的考虑吧!
为了保证顺利完成部署,最好两台数据库服务器各项参数尽量一致。主从同步配置好了之后,任何一台服务器重启,只要启动MySQL,同步会自动启动。
问题一:主服务器清除Binlog
1
2
3
4
5
6
7
8
9
|
-- 如果要 reset master,记住如下操作:
a. master lock table
b. slave finished the binlog replication
c. master reset master
d. master show master status | MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=120;
e. slave slave stop
f. master unlock table
g. slave change master to ***
h. slave slave start;
|
问题二:同步出现错误
1
2
3
4
5
6
|
-- Slave SQL错误 导致同步卡住的一种处理方法
-- 就是从库上跳过1条语句的执行,这个一定要慎重,看这条语句是否可以跳过,否则两边数据库就不一致了
mysql>stop slave;
mysql>set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql>start slave;
mysql>show slave status\G
|
另外数据日志的分析处理可以参考:https://www.linuxidc.com/Linux/2014-07/104676.htm
问题三:如果只想同步特定的表
如果想在从服务器只同步主服务器中某个特定库的某几张表,可以在从服务器/etc/my.cnf
配置文件中加入如下的配置:
1
2
3
4
5
6
7
8
9
10
|
# 忽略要同步的库
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
replicate-ignore-db=information_schema
replicate-ignore-db=your_ignore_db
# 指定要复制的库和相应的几张表名
replicate-do-db=your_db
replicate-do-table=your_db.table_name1
replicate-do-table=your_db.table_name2
|
(完)