MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)

 MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)

一.基础知识
1.Mysql作为目前世界上使用最广泛的免费数据库,但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面。因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 ,这样的方案来进行部署与实施的。
MySQL主从复制:客户机访问Master服务器来写数据库,客户机访问Slave服务 器来读数据库。这种情况下,需要客户端自行区分向何处写、从何处读。(不太理解,客户端如何区分)
MySQL主从复制+代理:客户机访问Proxy服务器,读、写请求交给Proxy识别,如果是写数据库操作则交给Master,如果是读数据库操作则交给Slave处理,具体由分配策略控制。这种情况下,无需客户端区分读、写目标,而是由Proxy服务器代劳了(原理),从而降低了客户端程序的复杂度。
mysql主从复制的原理
MySQL复制原理,其通过三个线程来完成,在master节点上运行的binlogdump线程以及在slave节点上运行的I/O线程和SQL线程。
1. master节点上的binlogdump线程,在slave与其正常连接的情况下,将binlog发送到slave上。
2.slave节点上的I/O线程,通过读取master节点发送的内容,并将数据复制到本地的relaylog中。
3.slave节点上的SQL线程,读取relaylog中的日志,并将其事务在本地执行。
二.SQL语句分类
数据定义语言(DDL),数据操作语言(DML),数据控制语言(DCL),事物控制语言(TCL)
DDL即Data Definition Language
DDL使用于:
  CREATE DATABASE————-创建新的数据库
  ALTER DATABASE————— 修改数据库
  CREATE TABLE———————创建表
  ALTER TABLE————————变更数据库表
  DROP TABLE—————————删除表
  CREATE INDEX————————建立索引
  DROP INDEX—————————删除索引
2.DML即Data Mainpulation Langusge
DML使用于:
  SELECT——————从数据库表中获取数据
  UPDATE——————更新数据库表中的数据
  DELETE——————从数据库表中删除数据
  INSERT INTO————向数据库表中插入数据
DCL即Data Control Language
DCL使用于:
  GRANT————授权
  REVOKE———撤销授权
  DENY————拒绝授权
TCL即Transaction Control Language
TCL使用于:
  SAVEPOINT———设置保存点
  ROLLBACK———回滚
  COMMIT————提交
mysql的二进制日志文件
二进制日志文件可以实现灾难数据恢复,另外可以应用到mysql复制数据同步。二进制日志包含了所有更新了数据或者已经潜在更新了的数据的所有语句。语句以事件的形式保存。
二进制文件内容
・所有更新了的数据或者已经潜在更新了的数据
・关于每个更新数据库的语句执行时间信息
作用
1)恢复(recovery)2)复制(replication)

二进制日志的启动:配置参数log-bin[=name],如果不指定name,则默认二进制日志文件名为主机名,后缀名为二级制日志的序列号,所在路径为数据库所在目录。
以index为后缀的文件为二进制日志的索引文件,用来存储过程生产的二进制日志。
配置
vim /etc/my.cnf

log-bin=[file-name] //用来指定二进制日志存放的位置。
binlog-do-db[=数据库名] //指定记录二进制日志的数据库

binlog-ingore-db[=数据库名] //指定不记录二进制日志的数据库

四.mysql的主从复制
环境:rhel6.5
两台主机:server1:master
server2:slave
1) 在两台主机上安装服务
master操作:
[root@server1 ~]# ls
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
[root@server1 ~]# yum install -y *
2) 异步复制
异步复制,所有复制节点的数据在一定时间内是不同步的.
[root@server1 ~]# vim /etc/my.cnf
log-bin=mysql-bin #启动二进制日志系统
binlog-do-db=test
#二进制需要同步的数据库名,如果需要同步多个库,例如要再同步 westos库,再添加一行“binlog-do-db=westos”,以此类推
server-id=1 #必须为 1 到 2的32次方–1 之间的一个正整数值
binlog-ignore-db=mysql #禁止同步 mysql 数据库
[root@server1 ~]# /etc/init.d/mysqld start
Initializing MySQL database: [ OK ]
Installing validate password plugin: [ OK ]
Starting mysqld: [ OK ]

[root@server1 ~]# grep password /var/log/mysqld.log
2017-08-03T11:48:31.045750Z 1 [Note] A temporary password is generated for root@localhost: ZP>U4uXy/9k! ##初始密码
2017-08-03T11:49:27.365187Z 0 [Note] Execution of init_file '/var/lib/mysql/install-validate-password-plugin.SlhsuE.sql' started.
2017-08-03T11:49:27.459464Z 0 [Note] Execution of init_file '/var/lib/mysql/install-validate-password-plugin.SlhsuE.sql' ended.
2017-08-03T11:49:29.608338Z 0 [Note] Shutting down plugin 'sha256_password'
2017-08-03T11:49:29.608342Z 0 [Note] Shutting down plugin 'mysql_native_password'
2017-08-03T11:49:32.398186Z 3 [Note] Access denied for user 'UNKNOWN_MYSQL_USER'@'localhost' (using password: NO)
[root@server1 ~]# mysql -p ##使用初始密码登陆
Enter password:
........

mysql> show databases; ##提示修改密码
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
mysql> ALTER USER root@localhost identified by 'Westos@222';
Query OK, 0 rows affected (0.12 sec)

mysql> show databases; ##密码修改后就可以使用数据库了
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)

mysql> set sql_log_bin=1; ##开启二进制日志同步
Query OK, 0 rows affected (0.00 sec)

mysql> grant replication slave on *.* to westos@'172.25.66.%' identified by 'Westos@222';
Query OK, 0 rows affected, 1 warning (0.10 sec)
##创建同步帐号,授权这个网段的所有主机都可以通过密码远程访问该数据库

mysql> show master status; ##显示master的信息,position指位置
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 693 | test | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql> create database test; #建立数据库test,并插入数据
Query OK, 1 row affected (0.10 sec)

mysql> use test;
Database changed
mysql> create table userdb (
-> username varchar(10) not null,
-> password varchar(20) not null);
Query OK, 0 rows affected (0.47 sec)

mysql> desc userdb;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | | NULL | |
| password | varchar(20) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> show master status; ##写入数据后数据的最后位置改变
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 1074 | test | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)



slave操作:
[root@server2 ~]# 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
root@server2 ~]# vim /etc/my.cnf
server-id=2
##从服务器 ID 号,不要和主 ID 相同,如果设置多个从服务器,每个从服务器必
须有一个唯一的 server-id 值,必须与主服务器的以及其它从服务器的不相同。
可以认为 server-id 值类似于 IP 地址:这些 ID 值能唯一识别复制服务器群集
中的每个服务器实例。
[root@server2 ~]# /etc/init.d/mysqld start
MySQL Daemon failed to start.
Starting mysqld: [FAILED]
##mysql启动失败,这里是因为之前安装包遗留下来的数据
[root@server2 ~]# cd /var/lib/mysql ##把/var/lib/mysql下的所有文件删除
[root@server2 mysql]# rm -fr *
[root@server2 mysql]# cd
[root@server2 ~]# /etc/init.d/mysqld start ##开启服务
Initializing MySQL database: [ OK ]
Installing validate password plugin: [ OK ]
Starting mysqld: [ OK ]

[root@server2 ~]# less /var/log/mysqld.log ##在日志里去拿开启服务时生成的初始密码
[root@server2 ~]# mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
[root@server2 ~]# grep password /var/log/mysqld.log
2017-08-03T11:42:38.013907Z 1 [Note] A temporary password is generated for root@localhost: dpLP1F/UlVer
2017-08-03T11:43:36.815716Z 0 [Note] Execution of init_file '/var/lib/mysql/install-validate-password-plugin.OWOOC9.sql' started.
2017-08-03T11:43:36.913716Z 0 [Note] Execution of init_file '/var/lib/mysql/install-validate-password-plugin.OWOOC9.sql' ended.
2017-08-03T11:43:38.884481Z 0 [Note] Shutting down plugin 'sha256_password'
2017-08-03T11:43:38.884484Z 0 [Note] Shutting down plugin 'mysql_native_password'
2017-08-03T11:43:41.759765Z 3 [Note] Access denied for user 'UNKNOWN_MYSQL_USER'@'localhost' (using password: NO)
2017-08-03T11:51:18.238311Z 4 [Note] Access denied for user 'root'@'localhost' (using password: NO)
[root@server2 ~]# mysql -p
Enter password:
......
mysql> show databases;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
mysql> ALTER USER root@localhost identified by 'Westos@222'; ##修改密码
Query OK, 0 rows affected (0.00 sec)

mysql> ^DBye

[root@server2 ~]# mysql -u westos -p -h 172.25.66.1 ##使用授权帐号和密码远程登陆master
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.17-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

mysql> ^DBye



2.master+slave实现数据同步
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# mysqlbinlog mysql-bin.000003
##在master日志文件中(这个日志的文件名来自master status的表格中)可以看到master在写入数据的记录即写入数据的每一个位置变化
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
.................
#170803 20:00:42 server id 1 end_log_pos 693 CRC32 0xc9e406d1 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1501761642/*!*/;
GRANT REPLICATION SLAVE ON *.* TO 'westos'@'172.25.66.%' IDENTIFIED WITH 'mysql_native_password' AS '*FF8C0F105C22DB42F119CADD8E07112EF5D80672'
/*!*/;
# at 693
#170803 20:04:17 server id 1 end_log_pos 758 CRC32 0xc58f1541 Anonymous_GTID last_committed=2 sequence_number=3
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 758
##下面我们将设置slave从这里也就是master开始写入数据的地方开始同步
#170803 20:04:17 server id 1 end_log_pos 852 CRC32 0xca40e1f1 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1501761857/*!*/;
create database test
/*!*/;
# at 852
#170803 20:06:44 server id 1 end_log_pos 917 CRC32 0x91bac314 Anonymous_GTID last_committed=3 sequence_number=4
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 917
#170803 20:06:44 server id 1 end_log_pos 1074 CRC32 0xf29616e1 Query thread_id=4 exec_time=1 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1501762004/*!*/;
create table userdb (
username varchar(10) not null,
password varchar(20) not null)
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;


[root@server2 ~]# mysql -pWestos@222
......

mysql> change master to master_host='172.25.66.1', master_user='westos',master_password='Westos@222', master_log_file='mysql-bin.000003', master_log_pos=758;
Query OK, 0 rows affected, 2 warnings (1.05 sec)

mysql> start slave;
Query OK, 0 rows affected (0.13 sec)

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.66.1
Master_User: westos
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1074
Relay_Log_File: server2-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
##Slave_IO_Running,Slave_SQL_Running如果都是 yes,表示从库的 I/O,Slave_SQL 线程都正确开启.表明数据库正在同步

mysql> show databases; ##数据已经完成同步
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| userdb |
+----------------+
1 row in set (0.00 sec)

mysql> select * from userdb;
+----------+----------+
| username | password |
+----------+----------+
| user1 | 123 |
+----------+----------+
1 row in set (0.00 sec)



3) 使用GTID模式
1.概念:GTID(Global Transaction Identifier)称为全局事务标示符,是由mysql服务器自动管理的在原始master上提交事务时被创建。GTID需要在全局的主-备拓扑结构中保持唯一性,每一个 GTID 代表一个数据库事务。GTID由两部分组成:
GTID = source_id:transaction_id
source_id: 用于标示源服务器,用server_uuid来表示
transaction_id: 则是根据在源服务器上第几个提交的事务来确定。transaction_id 是一个从 1 开始的自增计数,表示在这个主库上执行的第 n 个事务。MySQL 会保证事务与 GTID 之间的 1 : 1 映射。
工作原理:前面在slave端配置,进行change master to操作时,使用的是日志号(指定position),当master端的服务down掉了,就会在slave端选择一个日志号与原来的master最接近的作为master,但是,在另一个slave上,并没有指定新的master的信息,因此还要手动去指定,而使用gtid的话,slave通过寻找next的值,并不用指定master的二进制日志文件和日志号,所以使用gtid更能保证数据的完整性。
2.配置
[root@server1 mysql]# vim /etc/my.cnf ##开启gtid模式
gtid_mode=ON
enforce-gtid-consistency=true
[root@server1 mysql]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
[root@server1 mysql]# mysql -pWestos@222
...........
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into userdb values ('user2','123'); ##验证同步,在这里插入数据
Query OK, 1 row affected (0.14 sec)





[root@server2 ~]# vim /etc/my.cnf ##从机开启gtid模式
gtid_mode=ON
enforce-gtid-consistency=true ##强制GTID的一致性
[root@server2 ~]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
[root@server2 ~]# mysql -pWestos@222
...................
mysql> stop slave; ##在配置前先将slave关掉
Query OK, 0 rows affected (0.15 sec)

mysql> change master to master_host='172.25.66.1', master_user='westos',master_password='Westos@222',MASTER_AUTO_POSITION = 1;
Query OK, 0 rows affected, 2 warnings (0.37 sec)
##开启GTID时,slave在做同步复制时,无须找到binlog日志和POS点,直接change master to master_auto_position=1即可,自动找点同步。
mysql> start slave;
Query OK, 0 rows affected (0.03 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.66.1
Master_User: westos
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 154
Relay_Log_File: server2-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
mysql> set global read_only=on;
Query OK, 0 rows affected (0.00 sec)
##每次开启后务必确保Slave_IO_Running,Slave_SQL_Running是yes的状态
mysql> select * from test.userdb; ##查看数据是否同步
+----------+----------+
| username | password |
+----------+----------+
| user1 | 123 |
| user2 | 123 |
+----------+----------+
2 rows in set (0.00 sec)

mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| db |
| engine_cost |
| event |
| func |
| general_log |
| gtid_executed |
| help_category |
............
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
31 rows in set (0.00 sec)

mysql> select * from gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| abc561e2-7841-11e7-89f2-5254006b5f2a | 1 | 1 |
+--------------------------------------+----------------+--------------+
1 row in set (0.00 sec)
3.知识点简析
关于UUID:
在master的数据库目录中的auto.cnf文件中记录着source_id,在slave中也有记录

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第1张图片

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第2张图片

关于进程:
>master(可以是多线程)
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第3张图片
>slave(单线程同步)
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第4张图片

3) 并行复制(多SQL线程,加快复制速度,减少延时时间,基于库的并行复制--mysql5.6,基于组的并行复制--mysql5.7)
1.[未设置按组复制时,slave的mysql目录拥有master.info, relay-log.info 文件]
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第5张图片
Relay-log:记录了数据库的变化,由一系列文件组成,有IO线程写入
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第6张图片
Master:记录了备节点的连接信息
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第7张图片
并行复制的配置
[root@server1 mysql]# vim /etc/my.cnf
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16 ##
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
[root@server1 mysql]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
[root@server2 mysql]# vim /etc/my.cnf
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
[root@server2 mysql]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
并行复制配置完成后slave的mysql目录的master.info、relay-log.info 文件已经不存在
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第8张图片

在slave中show prosesslist 可以看到在配置文件里写入的设置
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第9张图片
mysql> show variables like '%sync%';
+-----------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------+-------+
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| innodb_flush_sync | ON |
| innodb_sync_array_size | 1 |
| innodb_sync_spin_loops | 30 |
| sync_binlog | 1 |
| sync_frm | ON |
| sync_master_info | 10000 |
| sync_relay_log | 10000 |
| sync_relay_log_info | 10000 |
+-----------------------------------------+-------+
##sync_binlog 1 同步频率,master的二进制日志每变更一次,同步一次,更新到磁盘
mysql> show variables like '%expire%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| disconnect_on_expired_password | ON |
| expire_logs_days | 0 |
+--------------------------------+-------+
expire_logs_days 0 ##日志清除时间,一天清除一次

四)Mysql的半同步复制(半同步的配置需要建立在异步复制配置正常的基础上)
知识点
通过优化I/O线程实现半同步
半同步复制即在master的dumper线程通知slave后,增加了一个ack,即是否成功收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,在设置的时间即rpl_semi_sync_master_timeout指定的时间还没有收到ack(这个时间的默认值为10000表示10s),那么将自动降级为普通的复制,直到异常修复。如果将这个值设置为无穷,则当slave没有返回值时,master就会一直等下去。
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第10张图片
3.Mysql半同步复制了解
Master插入半同步插件:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.17 sec)


Slave插入半同步插件:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.16 sec)
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第11张图片

部分参数介绍:
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第12张图片
rpl_semi_sync_master_timeout
##半同步的等待时间为10s,10s后如果还没有发送同步成功的信息,会自动转变为异步
rpl_semi_sync_master_enabled OFF
##此时半同步状态为关闭,当前主从复制模式为异步
rpl_semi_sync_master_wait_for_slave_count
##当多个从机时,只接收1个ack
mysql半同步实现
>先在slave端关闭I/O线程
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.19 sec)

>Master和slave端数据库设置半同步参数开启
Master:
mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi_sync%';
+-------------------------------------------+------------+
| 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.00 sec)
Slave:
mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)
>在slave端打开I/O线程,查看半同步成功字数,再在master中插入数据,查看半同步的成功记录
Slave:
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
Master:
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into userdb values ('user3','123');
Query OK, 1 row affected (0.15 sec)

mysql> show status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 354 |
| Rpl_semi_sync_master_tx_wait_time | 354 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
##+1
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

mysql> insert into userdb values ('user4','123');
Query OK, 1 row affected (10.22 sec)

mysql> show status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
##+1
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 354 |
| Rpl_semi_sync_master_tx_wait_time | 354 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)


Rpl_semi_sync_master_yes_tx ##使用半同步成功的次数,数据一致性性能提高
Rpl_semi_sync_master_no_tx
##使用半同步失败的次数,10s后没有得到反馈信息,会转为异步复制

当把从机的I/O线程关闭后,主数据库在进行对复制数据库的库进行更改时,在进行操作会等待10秒,增加了一次半同步传输的失败次数。
测试:
Slave:
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.14 sec)
Master:
mysql> show status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 354 |
| Rpl_semi_sync_master_tx_wait_time | 354 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

mysql> insert into userdb values ('user4','123');
Query OK, 1 row affected (10.22 sec) ##注意这里的时间

mysql> show status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 354 |
| Rpl_semi_sync_master_tx_wait_time | 354 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
Rpl_semi_sync_master_yes_tx,Rpl_semi_sync_master_no_tx数值随着我们的操作在发生变化。

读写分离
Server1: master
Server2:slave
Server3:proxy
[root@server3 ~]# ls
mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz
[root@server3 ~]# tar zxf mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz -C /usr/local/
[root@server3 ~]# cd /usr/local/
[root@server3 local]# ln -s mysql-proxy-0.8.5-linux-el6-x86-64bit/ mysql-proxy
[root@server3 local]# mkdir /usr/local/mysql-proxy/log
[root@server3 local]# mkdir /usr/local/mysql-proxy/etc
[root@server3 local]# cd mysql-proxy
[root@server3 mysql-proxy]# vim etc/mysql-proxy.conf
[mysql-proxy]
user=root
daemon=true
keepalive=true
log-level=debug
log-file=/usr/local/mysql-proxy/log/mysql-proxy.log
admin-username=admin
admin-password=westos
admin-lua-script=/usr/local/mysql-proxy/lib/mysql-proxy/lua/admin.lua
proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
proxy-backend-addresses=172.25.66.1:3306
proxy-read-only-backend-addresses=172.25.66.2:3306
plugins=proxy,admin
[root@server3 mysql-proxy]# chmod 660 etc/mysql-proxy.conf
[root@server3 mysql-proxy]# vim share/doc/mysql-proxy/rw-splitting.lua
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第13张图片
[root@server3 mysql-proxy]# bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/etc/mysql-proxy.conf
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第14张图片
[root@server1 ~]# mysql -pWestos@222
mysql> grant select,update,insert on *.* to admin@'172.25.66.%' identified by 'Westos@222';
Query OK, 0 rows affected, 1 warning (0.10 sec)
[root@server2 ~]# mysql -pWestos@222
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第15张图片


MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第16张图片

[root@server3 mysql-proxy]# mysql -h 172.25.66.3 -P 4041 -u admin -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.99-agent-admin

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show datadases;
ERROR 1105 (07000): use 'SELECT * FROM help' to see the supported commands
mysql> SELECT * FROM help;
+------------------------+------------------------------------+
| command | description |
+------------------------+------------------------------------+
| SELECT * FROM help | shows this help |
| SELECT * FROM backends | lists the backends and their state |
+------------------------+------------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM backends;
+-------------+------------------+---------+------+------+-------------------+
| backend_ndx | address | state | type | uuid | connected_clients |
+-------------+------------------+---------+------+------+-------------------+
| 1 | 172.25.66.1:3306 | unknown | rw | NULL | 0 |
| 2 | 172.25.66.2:3306 | unknown | ro | NULL | 0 |
+-------------+------------------+---------+------+------+-------------------+
多次访问:

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)_第17张图片




你可能感兴趣的:(MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy))