在以前的mysql版本中,读写分离的实现一般都是基于日志的主从复制实现的,这样会产生一个问题,就是master宕机之后,slave由于同步延时的问题,会导致master和slave内容不同,甚至会多个slave之间互相不同。所以为了解决这个问题,再mysql5.7.6版本之后加入了基于GTID的事务控制,具体的说就是每个事务由一个唯一的gtid标识,当slave都成功执行之后master才写入硬盘完成该事务,如果master突然宕机,那么就自动回滚。数据的一致性得到保证。
操作方法和普通的基于日志的主从复制差不了很多,主要就是打开两个开关
enforce_gtid_consistency = ON
gtid_mode = ON
那么就具体的介绍一下这种主从同步的搭建过程。
Master:
首先要修改mysql的配置文件,我这里的配置文件路径为/etc/mysql/mysql.conf.d/mysqld.cnf,基于docker,不同的版本位置可能会不一样,windows下多数都叫my.cnf,下载地址:https://hub.docker.com/r/alexzhuo/mysql/。
这里只截取要修改的那一段
修改前:
#server-id = 1
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
修改后
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
其实就是去掉了两个注释,打开了binlog,必须打开binlog主从之间同步才有据可依。
其中server-id是这个mysql集群中,每个节点都要有自己的id,不能重复,一般master设置为1,slave设置为2,3,4,5.如果这一行被注释掉了,那么slave节点是启动不起来的。
关于binlog_do_db,它是制定哪些库的操作会写入到binlog中,也就是同步哪些库,而binlog_ignore_db是哪些库不写入到binlog中,也就是不同步哪些库。一般情况下可以把这两行注释掉,也就是同步所有的库。在slave节点中也会有这样的配置,但是配置的字段不一样,在slave端进行控制可以降低master的压力,同时还可以精确到某个表是否同步,所以一般在slave节点上进行设置,可见下图:
然后再查看一下同步格式
mysql> show global variables like 'binlog%';
+-----------------------------------------+--------------+
| Variable_name | Value |
+-----------------------------------------+--------------+
| binlog_cache_size | 32768 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_error_action | ABORT_SERVER |
| binlog_format | ROW |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_gtid_simple_recovery | ON |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_row_image | FULL |
| binlog_rows_query_log_events | OFF |
| binlog_stmt_cache_size | 32768 |
+-----------------------------------------+--------------+
13 rows in set (0.00 sec)
注意这里的binlog_format是个重点,再mysql 5.7版本中,有三种模式,分别是
可以根据自己的需要进行选择,默认是row。
然后我们需要在master节点上创建一个用户,然后给它授权专门用来做复制任务,但是它不能select或者修改任何一张表。语句如下:
create user 'dba'@'%' identified by '123456';
grant replication slave on *.* to dba;
然后我们就可以将当前数据库的所有内容导出出来,然后导入新的数据库里。当然新的slave数据库也是个docker。导出语句如下
mysqldump --single-transaction --master-data=2 --triggers --routines --all-databases -uroot -p > all.sql
导出的内容为文本文件。
如果没有将server-id以及log_bin的注释打开,那么在导出数据库的时候就会报如下错误
root@701cc1949c81:/home/mysql# mysqldump --single-transaction --master-data=2 --triggers --routines --all-databases -uroot -p > all.sql
Enter password:
mysqldump: Error: Binlogging on server not active
然后我们就可以再开启一个新的docker,然后导入这个库,当然你首先要把刚才导出的all.sql传输到新docker容器上,导入语句为:
mysql -uroot -p < all.sql
然后作为从数据库,我们也要注意两个配置的地方
1是server-id,也要打开,并且不能和master的重复,方法跟上面一样,修改/etc/mysql/mysql.conf.d/mysqld.cnf这个文件。
修改前