MySQL 主从复制
MySQL 主从复制原理:
从库有两个线程 IO 线程和 SQL 线程
1. 从库的 IO 线程向主库的主进程发送请求, 主库验证从库, 交给主库 IO 线程负责数据传输;
2. 主库 IO 线程对比从库发送过来的 master.info 里的信息, 将 binlog 文件信息, 偏移量和 binlog 文件名等发送给从库
3. 从库接收到信息后, 将 binlog 信息保存到 relay-bin 中, 同时更新 master.info 的偏移量和 binlog 文件名
4. 从库的 SQL 线程不断的读取 relay-bin 的信息, 同时将读到的偏移量和文件名写道 relay-log.info 文件, binlog 信息写进自己的数据库, 一次同步操作完成.
5. 完成上次同步后, 从库 IO 线程不断的向主库 IO 线程要 binlog 信息
6. 从库如果也要做主库, 也要打开 log_bin 和 log-slave-update 参数
配置读写 mysql 主从复制的步骤:
1. 在主库与从库都安装 mysql 数据库
2. 在主库的配置文件 (/etc/my.cnf) 中配置 server-id 和 log-bin
3. 在登陆主库后创建认证用户并做授权.
4. 在从库的配置文件 (/etc/my.cnf) 中配置 server-id
5. 登陆从库后, 指定 master 并开启同步开关.
需要注意的是 server-id 主从库的配置是不一样的.
Server-id 存在作用:
MySQL 同步的数据中是包含 server-id 的, 而 server-id 用于标识该语句最初是从哪个 server 写入的. 因此 server-id 一定要有的
Server-id 不能相同的原因: 每一个同步中的 slave 在 master 上都对应一个 master 线程, 该线程就是通过 slave 的 server-id 来标识的; 每个 slave 在 master 端最多有一个 master 线程, 如果两个 slave 的 server-id 相同, 则后一个连接成功时, slave 主动连接 master 之后, 如果 slave 上面执行了 slave stop; 则连接断开, 但是 master 上对应的线程并没有退出; 当 slave start 之后, master 不能再创建一个线程而保留原来的线程, 那样同步就可能有问题;
在 MySQL 做主主同步时, 多个主需要构成一个环状, 但是同步的时候有要保证一条数据不会陷入死循环, 这里就是靠 server-id 来实现的;
MySQL 的主从复制 (gtid) 实验配置:
配置环境: rhel6.5 iptables selinx down
- 172.25.40.1 server1.example.com master
- 172.25.40.2 server2.example.com slave
安装包: mysql-5.7.17-1.el6.x86_64.rpm-bundle.tar
在 master 和 slave 上解压后安装 mysql 数据库:
- tar xf mysql-5.7.17-1.el6.x86_64.rpm-bundle.tar
- yum install -y mysql-community-client-5.7.17-1.el6.x86_64.rpm mysql-community-common-5.7.17-1.el6.x86_64.rpm mysql-community-libs-5.7.17-1.el6.x86_64.rpm mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm mysql-community-server-5.7.17-1.el6.x86_64.rpm
- /etc/init.d/mysqld start
- grep 'password' /var/log/mysqld.log
- ``` #筛选初始化是数据库登陆密码
登陆数据库后修改密码:
`alter user root@localhost identified by 'xxxxxxx';` ## 修改本地用户密码
1.Master 端的操作:
- vim /etc/my.cnf
- [mysqld]
- server-id=1
- log-bin=mysql-bin
- gtid_mode=ON #使用 gtid 模式
- enforce-gtid-consistency=true #强制使用 gtid
Slave 端的操作:
- [mysqld]
- server-id=2
- gtid_mode=ON
- enforce-gtid-consistency=true
注意: 在修改两台服务器的 mysql 配置文件时, 一定要保证 server-id 必须是不同的, server-id 的取值范围是: 2^32-1
2. 重新启动两台服务器上的 mysql
` /etc/init.d/mysqld restart`
3. 进入主库创建认证用户并授权
`grant replication slave on *.* to RedHat@'172.25.40.%' identified by 'xxxxxxxxxx';`
4. 进入 slave 端指定 master
- stop slave;
- change master to master_host='172.25.40.1',master_user='redhat',master_password='xxxxxxxxxx',master_auto_position=1;
- start slave;
5. 在设置半同步复制 master 端的操作
- mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
- Query OK, 0 rows affected (0.50 sec)
- mysql> set global rpl_semi_sync_master_enabled=1;
- Query OK, 0 rows affected (0.00 sec)
- mysql> show global variables like '%rpl_semi%';
- +-------------------------------------------+------------+
- | Variable_name | Value |
- +-------------------------------------------+------------+
- | rpl_semi_sync_master_enabled | ON |
- | rpl_semi_sync_master_timeout | 10000 |
- | rpl_semi_sync_master_trace_level | 32 |
- | rpl_semi_sync_master_wait_for_slave_count | 1 |
- | rpl_semi_sync_master_wait_no_slave | ON |
- | rpl_semi_sync_master_wait_point | AFTER_SYNC |
- +-------------------------------------------+------------+
- 6 rows in set (0.01 sec)
6.5. 在设置半同步复制 slave 端的操作
- mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
- Query OK, 0 rows affected (0.14 sec)
- mysql> set global rpl_semi_sync_slave_enabled=1;
- Query OK, 0 rows affected (0.00 sec)
- mysql> show global variables like '%rpl_semi%';
- +---------------------------------+-------+
- | Variable_name | Value |
- +---------------------------------+-------+
- | rpl_semi_sync_slave_enabled | ON |
- | rpl_semi_sync_slave_trace_level | 32 |
- +---------------------------------+-------+
- 2 rows in set (0.00 sec)
如果在 slave 端开启 io 线程后, 会自动调转为半同步模式进行数据传输
关闭 io 线程 在 master 上再进行事务时会等待 10s 后从半同步状态转为异步.
当第二次进行数据插入时会变成异步同步
MySQL 并行复制
多线程工作
Slave 端修改配置文件:
- [mysqld]
- slave-parallel-type=LOGICAL_CLOCK
- slave-parallel-workers=16 #开启 16 个线程工作
- master_info_repository=TABLE #以表的形式存放 master_info 的信息
- relay_log_info_repository=TABLE #以表的形式存放 relay_log_info 的信息
- relay_log_recovery=ON #
重启服务
`/etc/init.d/mysqld restart`
当进入数据库的 mysql 库中, 可以执行 sql 语句:
`select * from slave_master_info;`
可以看到原本在 / var/lib/mysql 下的 relay-log.info 的文件已经转为数据库中的表.
来源: http://www.linuxidc.com/Linux/2018-05/152175.htm