数据库的优化方案----mysql 主从复制,半同步复制 ,基于GTID的主从复制,读写分离

时间:2022-05-18 03:10:10

一.基础知识
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中的日志,并将其事务在本地执行。

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)

三)Mysql的半同步复制(半同步的配置需要建立在异步复制配置正常的基础上)
知识点
通过优化I/O线程实现半同步
半同步复制即在master的dumper线程通知slave后,增加了一个ack,即是否成功收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,在设置的时间即rpl_semi_sync_master_timeout指定的时间还没有收到ack(这个时间的默认值为10000表示10s),那么将自动降级为普通的复制,直到异常修复。如果将这个值设置为无穷,则当slave没有返回值时,master就会一直等下去。

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)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数值随着我们的操作

(四)读写分离
1、读写分离?
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
2、那么为什么要读写分离呢?
因为数据库的“写”(写10000条数据到oracle可能要3分钟)操作是比较耗时的。
但是数据库的“读”(从oracle读10000条数据可能只要5秒钟)。 所以读写分离,解决的是,数据库的写入,影响了查询的效率。
3 什么时候要读写分离?
数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用,利用数据库 主从同步 。可以减少数据库压力,提高性能。当然,数据库也有其它优化方案。memcache 或是 表折分,或是搜索引擎。都是解决方法。
4、主从复制与读写分离的关系
在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于前面我们学习过的rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份

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 
 Lua脚本默认最小4个最大8个以上的客户端连接才会实现读写分离(这是因为mysql-proxy会检测客户端连接, 当连接没有超过min_idle_connections预设值时,不会进行读写分离,即查询操作会发生到Master上),现改为最小1个最大2个,我们用vim修改/usr/local/lib/rw-splitting.lua脚本,改动内容如下所示:

    if not proxy.global.config.rwsplit then

            proxy.global.config.rwsplit = {

                    min_idle_connections = 1,

                    max_idle_connections = 2,



                    is_debug = false

            }

    end 
root@server3 mysql-proxy]# bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/etc/mysql-proxy.conf 
[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