mysql 5.7的MHA及组复制,读写分离及常见错误归类

一 MHA介绍

MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内;在复制框架中,MHA能够很好地解决复制过程中的数据一致性问题,由于不需要在现有的replication中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不需要修改现有的复制部署也是它的优势之处。

MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。

MHA提供了上述功能,使得其在适用于对高可用性,数据完整性要求高的场合,还有要求几乎non-stop的主库维护。

二 MHA环境搭建

1)软件安装(server1 MHA调度器)

yum install -y mha4mysql-manager-0.56-0.el6.noarch.rpm
mha4mysql-node-0.56-0.el6.noarch.rpm
perl-Config-Tiny-2.12-7.1.el6.noarch.rpm
perl-Email-Date-Format-1.002-5.el6.noarch.rpm
perl-Log-Dispatch-2.27-1.el6.noarch.rpm
perl-Mail-Sender-0.8.16-3.el6.noarch.rpm
perl-Mail-Sendmail-0.79-12.el6.noarch.rpm
perl-MIME-Lite-3.027-2.el6.noarch.rpm
perl-MIME-Types-1.28-2.el6.noarch.rpm
perl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm

2)集群组 一主两从(server2 主 server3 和 server4 从)安装

Yum install mha4mysql-node-0.56-0.el6.noarch.rpm -y

3)设置配置MHA 配置文件

mkdir /etc/masterha

cd /etc/masterha

vim app1.cnf

[server default]
manager_workdir=/etc/masterha  //设置manager的工作目录
manager_log=/etc/masterha/manager.log  //设置manager的日志
master_binlog_dir=/var/lib/mysql  //设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录
master_ip_failover_script=/usr/local/bin/master_ip_failover  //设置自动failover时候的切换脚本
master_ip_online_change_script=/usr/local/bin/master_ip_online_change //设置手动切换时候的切换脚本
password=James@123   //设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
user=root  //设置监控用户root
ping_interval=1   //设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover
remote_workdir=/tmp  //设置远端mysql在发生切换时binlog的保存位置
repl_password=James@123  //设置复制用户的密码
repl_user=rpl_user    //设置复制环境中的复制用户名
#report_script=/usr/local/send_report  //设置发生切换后发送的报警的脚本
#secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02
#shutdown_script=""  //设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
ssh_user=root      //设置ssh的登录用户名

[server2]
hostname=172.25.1.3
port=3306

[server3]
hostname=172.25.1.4
port=3306
candidate_master=1      //设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave
check_repl_delay=0  //默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

[server4]
hostname=172.25.1.5
port=3306
                                                                                                                     6,1           All

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第1张图片

4)配置一主两从服务器集群

Master:

1 grant replication slave on *.* to rpl_user@'%' identified by 'James@123';

2  Flush privileges;

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第2张图片

3 create database james;

4 use james

5 create table usertb(username varchar(25) not null,password varchar(25) not null);

6 insert into usertb values('user1','123');

7 insert into usertb values('user2','234');

Slave:(server3 和 server4)

1 change master to master_host='172.25.1.3',master_user='rpl_user',master_password='James@123',master_auto_position=1;

2 start slave;

3 show slave status\G;

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第3张图片

4 use james

5 select * from usertb;

6 set global read_only=1;

5)ssh 认证检查

server1(MHA调度软件)

1 ssh-keygen

2 ssh-copy-id 172.25.1.2

3 分发公钥和私钥

cd  /root/.ssh

scp -r .ssh/ [email protected]:

scp -r .ssh/ [email protected]:

scp -r .ssh/ [email protected]:

4 运行ssh检查脚本

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第4张图片四 检查整个环境状况

masterha_check_repl --conf=/etc/masterha/app1.cnf

主从授权配置

Master:

grant all on *.* to root@'%' identified by 'James@123';

Slave;

grant replication slave on *.* to rpl_user@'%' identified by 'James@123';

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第5张图片

三 配置VIP

1)通过脚本方式启动脚本的方式

vim /usr/local/bin/master_ip_failover

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;

my (
    $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
);

my $vip = '172.25.1.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr  del $vip dev eth0";

GetOptions(
    'command=s'          => \$command,
    'ssh_user=s'         => \$ssh_user,
    'orig_master_host=s' => \$orig_master_host,
    'orig_master_ip=s'   => \$orig_master_ip,
    'orig_master_port=i' => \$orig_master_port,
    'new_master_host=s'  => \$new_master_host,
    'new_master_ip=s'    => \$new_master_ip,
    'new_master_port=i'  => \$new_master_port,
);

exit &main();

sub main {

    print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {

        my $exit_code = 1;
        eval {
            print "Disabling the VIP on old master: $orig_master_host \n";
            &stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@\n";
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "start" ) {

        my $exit_code = 10;
        eval {
            print "Enabling the VIP - $vip on the new master - $new_master_host \n";
            &start_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
          exit $exit_code;
    }
    elsif ( $command eq "status" ) {
        print "Checking the Status of the script.. OK \n";
        exit 0;
    }
    else {
        &usage();
        exit 1;
    }
}

sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
     return 0  unless  ($ssh_user);
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}

sub usage {
    print
    "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
                                            

vim /usr/local/bin/master_ip_online_change

#!/usr/bin/env perl
use strict;
use warnings FATAL =>'all';

use Getopt::Long;

my $vip = '172.25.1.100/24';  # Virtual IP  
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr  del $vip dev eth0";
my $exit_code = 0;

my (
  $command,              $orig_master_is_new_slave, $orig_master_host,
  $orig_master_ip,       $orig_master_port,         $orig_master_user,
  $orig_master_password, $orig_master_ssh_user,     $new_master_host,
  $new_master_ip,        $new_master_port,          $new_master_user,
  $new_master_password,  $new_master_ssh_user,
);
GetOptions(
  'command=s'                => \$command,
  'orig_master_is_new_slave' => \$orig_master_is_new_slave,
  'orig_master_host=s'       => \$orig_master_host,
  'orig_master_ip=s'         => \$orig_master_ip,
  'orig_master_port=i'       => \$orig_master_port,
  'orig_master_user=s'       => \$orig_master_user,
  'orig_master_password=s'   => \$orig_master_password,
  'orig_master_ssh_user=s'   => \$orig_master_ssh_user,
  'new_master_host=s'        => \$new_master_host,
  'new_master_ip=s'          => \$new_master_ip,
  'new_master_port=i'        => \$new_master_port,
  'new_master_user=s'        => \$new_master_user,
  'new_master_password=s'    => \$new_master_password,
  'new_master_ssh_user=s'    => \$new_master_ssh_user,
);


exit &main();

sub main {

#print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";  

if ( $command eq "stop" || $command eq "stopssh" ) {

        # $orig_master_host, $orig_master_ip, $orig_master_port are passed.  
        # If you manage master ip address at global catalog database,  
        # invalidate orig_master_ip here.  
        my $exit_code = 1;
        eval {
            print "\n\n\n***************************************************************\n";
            print "Disabling the VIP - $vip on old master: $orig_master_host\n";
            print "***************************************************************\n\n\n\n";
&stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@\n";
            exit $exit_code;
        }
        exit $exit_code;
}
elsif ( $command eq "start" ) {

        # all arguments are passed.  
        # If you manage master ip address at global catalog database,  
        # activate new_master_ip here.  
        # You can also grant write access (create user, set read_only=0, etc) here.  
my $exit_code = 10;
        eval {
            print "\n\n\n***************************************************************\n";
            print "Enabling the VIP - $vip on new master: $new_master_host \n";
            print "***************************************************************\n\n\n\n";
&start_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
        exit $exit_code;
}
elsif ( $command eq "status" ) {
        print "Checking the Status of the script.. OK \n";
        `ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
        exit 0;
}
else {
&usage();
        exit 1;
}
}

# A simple system call that enable the VIP on the new master  
sub start_vip() {
`ssh $new_master_ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master  
sub stop_vip() {
`ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}

sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}

2)在MHA调度器(servre1)上开启MAH manager监控

[root@server1 masterha]# nohup masterha_manager --conf=/etc/masterha/app1.cnf &
[1] 2024
[root@server1 masterha]# nohup: ignoring input and appending output to `nohup.out'

注意:脚本的方式需要手动在master上增加VIP

ip addr add 172.25.1.100/24 dev eth0

3)在客户端访问vip

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第6张图片

4) 测试:

正常情况下从机server4上查看

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第7张图片

假如将主数据库done掉

在从数据库server4上查看

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第8张图片

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第9张图片

很明显的可以看出vip从server2主数据库漂移到备用数据库server3上,且备用数据库在MHA的调度下提升为新的主数据库,且保持着数据的一致性。

四 在线手动切换master到不同主机

1)server1上的MHA manager关闭 ,防止测试时候变成自动切换

 masterha_stop --conf=/etc/masterha/app1.cnf

2)由于上面的实验将master主机从serve2切换到 server3 ,那现在需要将master从server3手动在线切换到server2上

server1(MHAmananger):

[root@server1 masterha]# masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.1.3 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第10张图片

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第11张图片

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第12张图片

3)在数据库从机(server4)查看状态

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第13张图片

从这里可以看出手动切换已经成功然后我们查看以下之前为master数据库的server3的状态

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第14张图片

哈哈从这里发现,master已经变成slave端,并且和slave4一样,和自动切换不同的是,自动切换就需要设置备用master,并且如果master done掉之后,则需要重新配置新slave端

五 自动切换master

1)server1 上开启MHA mananger监控

2)假如done掉master(server2)

[root@server2 mysql]# ls
auto.cnf       binlog.index  client-cert.pem  ibdata1      james               private_key.pem           server2-relay-bin.index  sys
binlog.000001  ca-key.pem    client-key.pem   ib_logfile0  mysql               public_key.pem            server-cert.pem          test
binlog.000002  ca.pem        ib_buffer_pool   ib_logfile1  performance_schema  server2-relay-bin.000001  server-key.pem
[root@server2 mysql]# rm -rf *
[root@server2 mysql]# ls
[root@server2 mysql]# ls

 

 

3)查看server4 上状态

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第15张图片

说明在MHA mananger的调度下,master已经从server2 变成server3 ,说明自动切换没有问题~

六 组复制

MySQL 5.7 引入了新的变量slave-parallel-type,其可以配置的值有: 1. DATABASE (5.7之前默认值),基于库的并行复制方式; 2. LOGICAL_CLOCK (5.7新增值),基于组提交的并行复制方式; MySQL 5.6版本也支持所谓的并行复制,但是其并行只是基于DATABASE的,也就是基于库的。如果用户的MySQL数据库实例中存在多个DATABASE ,对于从机复制的速度的确可以有比较大的帮助,如果用户实例仅有一个库,那么就无法实现并行回放,甚至性能会比原来的单线程更差。 MySQL5.7中增加了一种新的并行模式:为同时进入COMMIT阶段的事务分配相同的序列号,这些拥有相同序列号的事务在备库是可以并发执行的。 MySQL 5.7真正实现的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进 行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。 因此下面的序列中可以并发的序列为(其中前面一个数字为last_committed ,后面一个数字为sequence_number ):

trx1 1…..2
trx2 1………….3
trx3 1…………………….4
trx4        2……………………….5
trx5               3…………………………..6
trx6                     3………………………………7
trx7                            6………………………………..8

备库并行规则:当分发一个事务时,其last_committed 序列号比当前正在执行的事务的最小sequence_number要小时,则允许执行。因此: 1. trx1执行,last_commit<2的可并发,trx2, trx3可继续分发执行 2. trx1执行完成后,last_commit < 3的可以执行, trx4可分发 3. trx2执行完成后,last_commit < 4的可以执行, trx5, trx6可分发 4. trx3、trx4、trx5完成后,last_commit < 7的可以执行,trx7可分发。

server1 (Maseter)

1)在主从复制的上基础上做修改(比如mysql安装)

2)vim /etc/my.cnf

server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW


transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="c149d92a-c685-4ac4-9560-37782655191f"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "172.25.73.2:24901"
loose-group_replication_group_seeds= "172.25.73.2:24901,172.25.73.3:24901,172.25.73.4:24901"
loose-group_replication_bootstrap_group=off
loose-group-replication-enforce_update_everywhere_checks=on
loose-group-replication-ip_whitelist="127.0.0.1/8,172.25.73.0/24"
loose-group-replication_single_primary_mode=off

3)为了环境的纯净性,删除之前的配置和数据库

cd /var/lib/mysql

rm -rf *

mysql -p

ALTER USER root@localhost identified by 'James@123';

4)进入master库进行参数配置

mysql> grant replication slave on *.* to rpl_user@'%' identified by 'James@123';
Query OK, 0 rows affected, 1 warning (0.32 sec)

mysql> Flush privileges;
Query OK, 0 rows affected (0.04 sec)

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> reset master;
Query OK, 0 rows affected (0.25 sec)

mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_user='rpl_user',master_password='James@123' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.77 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.32 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> STOP GROUP_REPLICATION;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (2.43 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | dbc42490-c39a-11e8-910c-525400389a39 | server2     |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

mysql> CREATE DATABASE test;
Query OK, 1 row affected (0.07 sec)

mysql> USE test;
Database changed
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
Query OK, 0 rows affected (0.68 sec)

mysql> INSERT INTO t1 VALUES (1, 'Luis');
Query OK, 1 row affected (0.15 sec)

mysql> SELECT * FROM t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+
1 row in set (0.00 sec)

mysql> SHOW BINLOG EVENTS;

server 2 (从库配置)

1)进入mysql进行配置

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> grant replication slave on *.* to rpl_user@'%' identified by 'James@123';
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
mysql> ALTER USER root@localhost identified by 'James@123';
Query OK, 0 rows affected (0.00 sec)

mysql> grant replication slave on *.* to rpl_user@'%' identified by 'James@123';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> Flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql>  reset master;
Query OK, 0 rows affected (0.40 sec)

mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)

mysql>  change master to master_user='rpl_user',master_password='James@123' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.57 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.21 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (6.69 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 08636553-c39b-11e8-952e-525400f1f82b | server3     |        3306 | ONLINE       |
| group_replication_applier | dbc42490-c39a-11e8-910c-525400389a39 | server2     |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
2 rows in set (0.00 sec)

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

mysql> select * from t1
    -> ;
ERROR 1046 (3D000): No database selected
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> select * from t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+
1 row in set (0.00 sec)

mysql> 

server3 (从库配置)

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER USER root@localhost identified by 'James@123';
Query OK, 0 rows affected (0.00 sec)

mysql> grant replication slave on *.* to rpl_user@'%' identified by 'James@123';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> Flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> reset master;
Query OK, 0 rows affected (0.41 sec)

mysql>  set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)

mysql> change master to master_user='rpl_user',master_password='James@123' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.55 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.20 sec)

mysql>  START GROUP_REPLICATION;
Query OK, 0 rows affected (3.14 sec)

mysql>  SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 08636553-c39b-11e8-952e-525400f1f82b | server3     |        3306 | ONLINE       |
| group_replication_applier | 09120784-c39b-11e8-92b8-5254004d6a22 | server4     |        3306 | ONLINE       |
| group_replication_applier | dbc42490-c39a-11e8-910c-525400389a39 | server2     |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

mysql> 

七 读写分离

mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个mysql-server。
它使用mysql协议,任何使用mysql-client的上游无需修改任何代码,即可迁移至mysql-proxy上。
mysql-proxy最基本的用法,就是作为一个请求拦截,请求中转的中间层:
进一步的,mysql-proxy可以分析与修改请求。拦截查询和修改结果,需要通过编写Lua脚本来完成。
mysql-proxy允许用户指定Lua脚本对请求进行拦截,对请求进行分析与修改,它还允许用户指定Lua脚本对服务器的返回结果进行修改,加入一些结果集或者去除一些结果集均可。
所以说,根本上,mysql-proxy是一个官方提供的框架,具备良好的扩展性,可以用来完成:
sql拦截与修改
性能分析与监控
读写分离
请求路由等

1)实验环境

master:server2

slave :server3

proxy:server4

2)server4 proxy安装

tar zxf mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz  -C  /usr/local/

cd /usr/local/

ln -s mysql-proxy-0.8.5-linux-el6-x86-64bit/   mysql-proxy

3)启动proxy

cd mysql-proxy/bin

/usr/local/mysql-proxy/bin/mysql-proxy

4 ) cd /usr/local/mysql-proxy

mkdir conf

5)编辑i配合文件

vim  mysql-proxy.conf

[mysql-proxy]
 user=root   
 proxy-address=0.0.0.0:3306   # 本机监听的地址及端口
 proxy-backend-addresses=172.25.1.3:3306
                              # 配置读写服务器,IP及端口  server2
 proxy-read-only-backend-addresses=172.25.1.4:3306
                              # 配置只读服务器,IP及端口   server3
 proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
                              # 用这个lua脚本来实现读写分离
 log-file=/usr/local/mysql-proxy/logs/mysql-proxy.log
                              # 服务日志
 log-level=debug              # 日志模式设置为debug模式,方便调试
 keepalive=true               # 持续连接
 daemon=true                  # 打入后台

6 ) 编写读写分离lua脚本

cd /usr/local/mysql-proxy/share/doc/mysql-proxy

vim rw-splitting.lua

7 )给脚本权限设置

chmod 660 /usr/local/mysql-proxy/conf/mysql-proxy.conf

8 )建立接受日志路径

cd /usr/local/mysql-proxy/

mkdir logs/

9 )运行脚本

/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/mysql-proxy.conf

10)master (server2)

create database test;

use test;

create table usertb(username varchar(25) not null, password varchar(25) not null);

insert into usertb value('user1','123');

grant select ,insert,update on test.* to whh@'%' identified by 'James@123';

11)slave端查看

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第16张图片

12 )proxy端测试

安装lsof

yum install -y lsof

lsof -i :3306

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第17张图片

 

八 mysql常见错误的解决方案

错误1

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第18张图片

错误原因:主库删除的表在从库中不存在,导致从库在遇到删除不存在表的错误时无法继续同步

解决方法:利用slave-skip-errors参数,跳过对于的1146错误(这个参数是一个只读的,需要在配置文件中修改,并重启从库)

具体方法:

1 )编辑vim /etc/my.cnf 增加

slave_skip_errors=1146 

2)重启数据库/etc/init.d/mysqld restart

3)进入从库查看状态

mysql 5.7的MHA及组复制,读写分离及常见错误归类_第19张图片

 

4)退出数据库,删除掉/etc/my.cnf slave_skip_errors=1146

5 )重新进入数据库(生产环境建议不要重启数据库)

后续增加...

 

你可能感兴趣的:(mysql 5.7的MHA及组复制,读写分离及常见错误归类)