使用数据库同步的方法解决数据传输的问题,但因为使用mysql 5.5版本时,设置的主从复制在数据量较大或者网络拥塞的时候延迟会更高,而且经过查资料,老版本是无法从根本上改善这个问题的。最近了解了MySQL 5.7版本的特性,知道了5.7版本的基于组提交的并行复制可以更大的改善这个问题。接下来对相关的内容进行详细的总结和概括。
(1) 在MySQL 5.6之前的版本里,有三个线程参与,都是单线程:Binlog Dump(主) ----->IO Thread (从) -----> SQL Thread(从)。其中IO Thread线程负责从主库拿binlog并写到relaylog,sql_thread 线程负责读relaylog并执行。复制出现延迟一般出在两个地方
a、SQL线程忙不过来(可能需要应用数据量较大,可能和从库本身的一些操作有锁和资源的冲突;)
虽然主库可以并发写,但Slave_SQL_Running线程不可以并发写(主要原因)。
b、网络抖动导致IO线程复制延迟(次要原因)。
(2) MySQL从5.6开始有了多线程的概念,可以并发还原数据,即并行复制技术。多线程的思路就是把sql_thread 变成分发线程,然后由一组worker_thread来负责执行。MySQL 5.6中,设置参数slave_parallel_workers = 4,即可有4个SQL Thread(coordinator线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。但是其并行只是基于Schema的,也就是基于库的。如果数据库实例中存在多个Schema,这样设置对于Slave复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,所以基于库的并发一般是没什么用的,不过其也有一定优势:
对于可以按表分发的场景,可以通过将表迁到不同的库,来应用此策略,有可操作性。
(1)新版本增加了一种类型,变成了两种类型
1、DATABASE 基于库的并行复制 , 每个数据库对应一个复制线程(5.6版本就有了,然并卵);
2、LOGICAL_CLOCK 基于组提交的并行复制方式,同一个数据库下可以有多个线程(对大多数数据库更实用)。
对于第二种类型,设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一个schema下,slave_parallel_workers中的worker线程并发执行relay log中主库提交的事务。
(2)从MySQL官方文件看,其并行复制的要实现的目标是支持表级的并行复制和行级的并行复制,行级的并行复制通过解析ROW格式的二进制日志的方式来完成。
(3)5.7版本基于组提交的并行复制核心思想是:一个组提交的事务都是可以并行回放的,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。
主服务器:(1)系统:windows 7 (2)数据库:MySQL 5.7.18
从服务器(虚拟机):(1)windows 7 (2)数据库:mysql 5.7.18
(1)在主服务器上建立需同步的数据库 create database test; 并建立两张表
CREATE TABLE `backup_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) CHARACTER SET utf8 NOT NULL,
`sex` varchar(2) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
CREATE TABLE `user` (
`User_ID` int(50) NOT NULL,
`User_Name` char(100) DEFAULT NULL,
PRIMARY KEY (`User_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(2)对于windows系统,直接按键windows+R键弹出运行窗口,输入地址C:\ProgramData\MySQL\MySQL Server 5.7,找到my.ini配置文件设置
[mysqld]
# 开启log-bin日志
log-bin=mysql-bin
server-id=1
# 我这里要复制名为test的数据库
binlog-do-db=test
然后再找到参数或者添加参数设置如下(这两个参数控制着二进制日志刷新的速度,先按下不表):
innodb_flush_log_at_trx_commit=1
sync_binlog=1
(3)然后root用户登录数据库,新建一个用户并授权(我这里设置为testuser用户,密码也是testuser,IP找到主服务器的ip写上)
CREATE USER 'testuser'@'192.168.0.%' IDENTIFIED BY 'testuser';
GRANT REPLICATION SLAVE ON *.* TO 'testuser'@'%';
注释:加了%则ip必须要用单引号括起来,%匹配任意。
(4)再开一个会话,连接mysql,执行 SHOW MASTER STATUS; 显示如下,记住那个mysql-bin.000002和position的值
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 412 | test | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
(1)从服务器的server-id设置成2,且同样要在目录 C:\ProgramData\MySQL中找到my.ini文件打开进行设置 (ProgramData文件夹可能是隐藏的,直接输入地址栏就能找到),后面的设置可直接写在server-id后面,同样是在该目录下的my.ini中
server-id=2 #识别服务器的唯一值
replicate-do-db=test #要同步的数据库
replicate-do-table=test.bakeup_table #要同步的表,改成自己的数据库和表
replicate-do-table=test.user #要同步的第二个表
(2)在上面设置的参数之后紧随下面的参数
skip-slave-start=true #跳过slave线程启动
read_only=ON #开启的只读模式
relay-log=relay-bin
relay-log-index=relay-bin.index
(3)配置寻找主服务器,然后启动从服务器。先输入start slave;然后执行如下命令:
CHANGE MASTER TO
MASTER_HOST='主服务器ip',
MASTER_USER='testuser', #新建的用户
MASTER_PASSWORD='testuser', #我的用户密码
MASTER_LOG_FILE='mysql-bin.000002', #上图查询出的同步文件
MASTER_LOG_POS=412; #上图查询出的同步点(即:position下的值)
(4)接下来配置从服务器上并行复制的参数(开启 Enhanced Multi-Threaded Slave)
A、master_info_repository
开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并 行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前InnoSQL的版本中,添加了参数来控制刷新 master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,推荐将master_info_repository设置为TABLE,来减小这部分的开销。
B、slave_parallel_workers
若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1 个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此 slave_parallel_workers=1的性能反而比0还要差。
C、要开启Enhanced Multi-Threaded Slave,只需要设置如下参数即可:
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16 #16为设置的并发线程个数,之后根据项目对数据传输的具体要求再更改
#一个schema下,slave_parallel_workers中的worker线程并发执行relay log中主库提交的事务
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
注:变量slave-parallel-type可以有两个值
a、DATABASE 为默认值:基于库的并行复制方式;
b、LOGICAL_CLOCK:基于组提交的并行复制方式
slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。
(5)最后保存my.ini并运行services.msc,重启mysql服务。
(6)同样,在从服务器上建立相同名的空数据库test以及相同的表。
执行 start slave;
再查看其状态,执行
show slave status\G;
结果如下:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.193
Master_User: testuser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 412
Relay_Log_File: slave-relay-bin.000007
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes <<<--------------------------此处可以看到
Slave_SQL_Running: Yes <<<--------------------------这两个线程都在运行
Replicate_Do_DB: test
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 412
Relay_Log_Space: 951
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: ed1d6bc3-51a6-11e7-a527-083e8e9a4d6f
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more up
dates <<<<<<<<<<<<<<<<<<---------------------------此处可以看到这个线程正在等待接受数据
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
查看一下正在执行等待接收数据的所有线程,结果如下:
所有线程都在等待接受数据,设置成功!
接下来就可以在主数据库中添加记录了, 为方便添加数据,这里我选用navicat来添加数据
(1)在主数据库中的两个表中都添加数据,同时保存。
(2)然后在从数据库中进行查找,结果如下:
至此,测试完成,配置成功!
参考文章:http://dinglin.iteye.com/blog/2272079
http://sky66.blog.51cto.com/2439074/1688047/
http://www.linuxidc.com/linux/2014-05/101450.htm——Linux公社
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢!