MYSQL HA 之02(MYSQL5.7双主配置)

2019-09-26  本文已影响0人  轻飘飘D
  1. 统一设置hosts(兩台)
[root@XAG137 usr]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.40.137 XAG137
192.168.40.138 XAG138
  1. 配置SSH无密码登录认证
[root@XAG137 ~]# ssh-keygen -t rsa
#一路回车,直到完成
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.40.138

[root@XAG138 /]# ssh-keygen -t rsa
#一路回车,直到完成
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.40.137

#測試免密
[root@XAG137 ~]# ssh XAG138
Are you sure you want to continue connecting (yes/no)? yes
[root@XAG138 ~]# exit
logout

[root@XAG137 ~]# ssh XAG138
Last login: Thu Sep 19 17:36:05 2019 from 192.168.40.137

[root@XAG138 /]# ssh XAG137
Are you sure you want to continue connecting (yes/no)? yes
[root@XAG137 ~]# exit
logout

[root@XAG138 /]# ssh XAG137
Last login: Thu Sep 19 17:36:58 2019 from 192.168.40.138
  1. 时间同步
[root@XAG137 ~]#  ssh XAG138 date;

发现时间不同步,进行时间同步,依据当前时间为准
[root@XAG137 ~]# ssh XAG138  "date -s '2019-09-19 17:42:00'";
  1. 修改配置(兩台)
shell> echo "fs.file-max=65535" >> /etc/sysctl.conf
shell> sysctl -p

shell># mkdir /usr/local/mysql/iblog
shell># chown mysql:mysql /usr/local/mysql/iblog
shell># chown mysql.mysql -R /usr/local/mysql/
  1. 在各个节点安装半同步插件
在192.168.40.137、138上:
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; 
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_master_enabled=on;  

6.創建測試DB(主DB--137)

root@127.0.0.1 : (none)【05:52:23】4 SQL->create database if not exists test default charset utf8 collate utf8_general_ci;

root@127.0.0.1 : (none)【06:02:10】5 SQL->show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |

root@127.0.0.1 : (none)【09:17:02】17 SQL->use test;

create table test_scheduler
(
  sch_seq int auto_increment not null,
  sch_name varchar(50),
  sch_createtime datetime,
  primary key(sch_seq)
) auto_increment=1001;

root@127.0.0.1 : test【09:17:35】19 SQL->insert into test_scheduler(sch_name,sch_createtime) values('sch01',now());

root@127.0.0.1 : test【09:17:57】20 SQL->insert into test_scheduler(sch_name,sch_createtime) values('sch01',now());

root@127.0.0.1 : test【09:18:00】21 SQL->select * from test_scheduler;
+---------+----------+---------------------+
| sch_seq | sch_name | sch_createtime      |
+---------+----------+---------------------+
|    1001 | sch01    | 2019-09-20 09:17:57 |
|    1003 | sch01    | 2019-09-20 09:18:00 |
+---------+----------+---------------------+

7.修改 /etc/my.cnf配置

137上新加如下內容:

#雙主配置新加配置項
#定义了从库从主库获取数据等待的秒数,超过这个时间从库会主动退出读取,中断连接,并尝试重连
slave_net_timeout=15
#信任子程序的创建者(解決mysql主從同步時错误1418)
log-bin-trust-function-creators=1
#步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_increment=2
#起始值。一般填第n台主MySQL。此时为第一台主MySQL
auto_increment_offset=1
#要同步的数据库,默认所有库
replicate-do-db=test
#二进制日志自动删除/过期的天数。默认值为 0,表示不自动删除。
expire_logs_days=7
#跳过主从复制中遇到的所有错误或指定类型的错误,避免 slave 端复制中断。
#如: 1062 错误是指一些主键重复, 1032 错误是因为主从数据库数据不一致
slave_skip_errors=1062,1032,1007,1008,1050,1051,1054,1060,1061,1068,1094,1146

#开启半同步复制  否则自动切换主从的时候会报主键错误
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 500
# slave --MySQL 5.7开启Enhanced Multi-Threaded 在Slave的my.cnf配置:
#变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式
slave-parallel-type=LOGICAL_CLOCK
#提交的事务都是可以并行回放(配合binary log group commit);
slave-parallel-workers=16
#将master.info和relay.info保存在表中,默认是Myisam引擎,官方建议用  
master_info_repository=TABLE
relay_log_info_repository=TABLE
#启用relaylog的自动修复功能,避免由于网络之类的外因造成日志损坏,主从停止。
relay_log_recovery=ON
relay_log_purge=ON 

#GTID
gtid_mode = on
enforce_gtid_consistency = 1
#做为从库时,数据库的修改也会写到bin-log里
log_slave_updates   = 1


138上新加如下內容:

#雙主配置新加配置項
#定义了从库从主库获取数据等待的秒数,超过这个时间从库会主动退出读取,中断连接,并尝试重连
slave_net_timeout=15
#信任子程序的创建者(解決mysql主從同步時错误1418)
log-bin-trust-function-creators=1
#步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_increment=2
#起始值。一般填第n台主MySQL。此时为第一台主MySQL
auto_increment_offset=2
#要同步的数据库,默认所有库
replicate-do-db=test
#二进制日志自动删除/过期的天数。默认值为 0,表示不自动删除。
expire_logs_days=7
#跳过主从复制中遇到的所有错误或指定类型的错误,避免 slave 端复制中断。
#如: 1062 错误是指一些主键重复, 1032 错误是因为主从数据库数据不一致
slave_skip_errors=1062,1032,1007,1008,1050,1051,1054,1060,1061,1068,1094,1146

#开启半同步复制  否则自动切换主从的时候会报主键错误
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 500
# slave --MySQL 5.7开启Enhanced Multi-Threaded 在Slave的my.cnf配置:
#变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式
slave-parallel-type=LOGICAL_CLOCK
#提交的事务都是可以并行回放(配合binary log group commit);
slave-parallel-workers=16
#将master.info和relay.info保存在表中,默认是Myisam引擎,官方建议用  
master_info_repository=TABLE
relay_log_info_repository=TABLE
#启用relaylog的自动修复功能,避免由于网络之类的外因造成日志损坏,主从停止。
relay_log_recovery=ON
relay_log_purge=ON 

#GTID
gtid_mode = on
enforce_gtid_consistency = 1
#做为从库时,数据库的修改也会写到bin-log里
log_slave_updates   = 1

#slave_skip_errors 錯誤碼說明
ddl_exist_errors,该参数包含一系列error code(1007,1008,1050,1051,1054,1060,1061,1068,1094,1146)
    一些error code代表的错误如下:
    1007:数据库已存在,创建数据库失败
    1008:数据库不存在,删除数据库失败
    1050:数据表已存在,创建数据表失败
    1051:数据表不存在,删除数据表失败
    1054:字段不存在,或程序文件跟数据库有冲突
    1060:字段重复,导致无法插入
    1061:重复键名
    1068:定义了多个主键
    1094:位置线程ID
    1146:数据表缺失,请恢复数据库
    1053:复制过程中主服务器宕机
    1062:主键冲突 Duplicate entry '%s' for key %d

  1. 在主库创建同步复制用户
[root@XAG137 ~]# mysql.login

root@127.0.0.1 : (none)【06:58:46】1 SQL->CREATE USER 'repl'@'%' IDENTIFIED BY 'rep123'; 

root@127.0.0.1 : (none)【06:58:57】2 SQL->grant replication slave on *.* to 'repl'@'%' identified by 'rep123';

root@127.0.0.1 : (none)【06:59:09】3 SQL->show variables like '%server%';
+---------------------------------+--------------------------------------+
| Variable_name                   | Value                                |
+---------------------------------+--------------------------------------+
| character_set_server            | utf8mb4                              |
| collation_server                | utf8mb4_general_ci                   |
| innodb_ft_server_stopword_table |                                      |
| server_id                       | 137                                  |
| server_id_bits                  | 32                                   |
| server_uuid                     | 3e7915f5-daab-11e9-ac9b-000c2929f2d3 |
+---------------------------------+--------------------------------------+

  1. reset (兩台)
root@127.0.0.1 : test【09:18:12】22 SQL->reset master;

root@127.0.0.1 : test【09:19:55】23 SQL->show master status; 
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 |      154 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
  1. 在192.168.40.137 主库上执行备份
[root@XAG137 ~]# cd /usr/local/src
[root@XAG137 src]# ls
mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz
[root@XAG137 src]# mysqldump -uroot -p --master-data=2 --single-transaction --default-character-set=utf8 -R --triggers -A >all2.sql
Enter password: 
[root@XAG137 src]# ls
all2.sql  mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz

#查看上备份时刻Binlog的名称和位置,MASTER_LOG_FILE 和 MASTER_LOG_FILE
[root@XAG137 src]# head -n 30 all2.sql|grep -i "CHANGE MASTER TO"
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=154;

or

root@127.0.0.1 : test【09:20:18】24 SQL->show master status; 
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 |      154 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
  1. 在备库上执行恢复及同步
#将all.sql拷贝到 192.168.40.138 备库机器上
[root@XAG137 src]# scp all2.sql root@192.168.40.138:/home

[root@XAG138 /]# cd /home
[root@XAG138 home]# mysql -uroot -p<all2.sql
[root@XAG138 home]# mysql.login

#如开启GTID后用下行,可不用下下行(下下行会报错)
change master to master_host='192.168.40.137',master_user='repl',master_password='rep123',master_port=3306,master_auto_position=1;

mysql> change master to master_host='192.168.40.137',master_user='repl',master_password='rep123',master_port=3306,master_log_file='mysql-bin.000001',master_log_pos=154,MASTER_HEARTBEAT_PERIOD=10,MASTER_CONNECT_RETRY=10, MASTER_RETRY_COUNT=86400;

#slave_net_timeout(全局变量):MySQL5.7.7之后,默认改成60秒。该参数定义了从库从主库获取数据等待的秒数,
#超过这个时间从库会主动退出读取,中断连接,并尝试重连。

#master_heartbeat_period:复制心跳的周期。默认是slave_net_timeout的一半。Master在没有数据的时候,
#每master_heartbeat_period秒发送一个心跳包,这样 Slave 就能知道 Master 是不是还正常。
#slave_net_timeout是设置在多久没收到数据后认为网络超时,之后 Slave 的 IO 线程会重新连接 Master 。
#结合这两个设置就可以避免由于网络问题导致的复制延误。master_heartbeat_period 单位是秒,可以是个带上小数,如 10.5,最高精度为 1 毫秒。

#重试策略为:
#备库过了slave-net-timeout秒还没有收到主库来的数据,它就会开始第一次重试。然后每过 master-connect-retry 秒,备库会再次尝试重连主库。
#直到重试了 master-retry-count 次,它才会放弃重试。如果重试的过程中,连上了主库,那么它认为当前主库是好的,
#又会开始 slave-net-timeout 秒的等待。slave-net-timeout 的默认值是 60 秒, master-connect-retry 默认为 60 秒,
# master-retry-count 默认为 86400 次。也就是说,如果主库一分钟都没有任何数据变更发送过来,备库才会尝试重连主库。

OR 通过如下命令修改
stop slave;
change master to master_connect_retry=10;
change master to MASTER_HEARTBEAT_PERIOD =8;
start slave;

#启动B库上的主从复制
mysql>  start slave;
mysql> show slave status\G
----------------------------------------------
        Slave_IO_Running: No
        Slave_SQL_Running: Yes
        Last_IO_Errno: 1236
        Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

root@127.0.0.1 : (none)【09:56:28】2 SQL->stop slave;

root@127.0.0.1 : (none)【10:00:10】3 SQL->reset slave;

root@127.0.0.1 : (none)【10:00:18】4 SQL->start slave;
root@127.0.0.1 : (none)10:00:245 SQL->show slave status\G
*************************** 1. row ***************************
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

#记下下面两个参数的值,后面会在A库执行
root@127.0.0.1 : (none)【09:42:39】5 SQL->show master status;
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 |   828749 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
  1. 在A库192.168.40.137上执行同步
mysql> change master to master_host='192.168.40.138',master_port=3306,master_user='repl',master_password='rep123',master_log_file='binlog.000001',master_log_pos=828749,MASTER_HEARTBEAT_PERIOD=10,MASTER_CONNECT_RETRY=10, MASTER_RETRY_COUNT=86400;
mysql> start slave;
mysql> show slave status\G
----------------------------------------------
        Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
  1. 備庫測試
root@127.0.0.1 : test【10:29:27】14 SQL->insert into test_scheduler(sch_name,sch_createtime) values('sch02',now());

root@127.0.0.1 : test【10:29:31】15 SQL->select * from test_scheduler;
+---------+----------+---------------------+
| sch_seq | sch_name | sch_createtime      |
+---------+----------+---------------------+
|    1001 | sch01    | 2019-09-20 09:17:57 |
|    1003 | sch01    | 2019-09-20 09:18:00 |
|    1004 | sch02    | 2019-09-20 10:29:31 |
+---------+----------+---------------------+

14.主庫測試

root@127.0.0.1 : test【10:28:03】32 SQL->select * from test_scheduler;
+---------+----------+---------------------+
| sch_seq | sch_name | sch_createtime      |
+---------+----------+---------------------+
|    1001 | sch01    | 2019-09-20 09:17:57 |
|    1003 | sch01    | 2019-09-20 09:18:00 |
|    1004 | sch02    | 2019-09-20 10:29:31 |
+---------+----------+---------------------+

root@127.0.0.1 : test【10:31:05】33 SQL->insert into test_scheduler(sch_name,sch_createtime) values('sch01',now());

root@127.0.0.1 : test【10:31:34】34 SQL->select * from test_scheduler;
+---------+----------+---------------------+
| sch_seq | sch_name | sch_createtime      |
+---------+----------+---------------------+
|    1001 | sch01    | 2019-09-20 09:17:57 |
|    1003 | sch01    | 2019-09-20 09:18:00 |
|    1004 | sch02    | 2019-09-20 10:29:31 |
|    1005 | sch01    | 2019-09-20 10:31:34 |
+---------+----------+---------------------+
  1. 備庫查詢
root@127.0.0.1 : test【10:29:42】16 SQL->select * from test_scheduler;
+---------+----------+---------------------+
| sch_seq | sch_name | sch_createtime      |
+---------+----------+---------------------+
|    1001 | sch01    | 2019-09-20 09:17:57 |
|    1003 | sch01    | 2019-09-20 09:18:00 |
|    1004 | sch02    | 2019-09-20 10:29:31 |
|    1005 | sch01    | 2019-09-20 10:31:34 |
+---------+----------+---------------------+
  1. 开启事件调度器(兩台)
在 my.cnf 的 mysqld 下配置 event_scheduler=1

[root@XAG138 binlog]# cat /etc/my.cnf | grep event_scheduler
event_scheduler=1

#重啟MYSQL
[root@XAG137 src]# service mysqld restart

root@127.0.0.1 : (none)【10:54:45】1 SQL->SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | ON    |
+-----------------+-------+

root@127.0.0.1 : (none)【10:54:47】2 SQL->SELECT @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| ON                |
+-------------------+
  1. 创建存储过程(主機137)
#存储过程
DROP PROCEDURE IF EXISTS  proc_test_scheduler;

DELIMITER $$

create procedure proc_test_scheduler()
LANGUAGE SQL
DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
begin
 delete from test_scheduler where sch_createtime<date_sub(now(),interval 5 minute);
 insert into test_scheduler(sch_name,sch_createtime) values(uuid(),now());
end$$

DELIMITER ;

#存储过程
DROP PROCEDURE IF EXISTS  proc_test_scheduler2;

DELIMITER $$

create procedure proc_test_scheduler2()
LANGUAGE SQL
DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
begin
 delete from test_scheduler where sch_createtime<date_sub(now(),interval 5 minute);
 insert into test_scheduler(sch_name,sch_createtime) values(@@server_id,now());
end$$

DELIMITER ;
  1. 主備都調用 存儲過程測試
root@127.0.0.1 : test【10:57:42】18 SQL-> call proc_test_scheduler();

#兩邊都調用後查詢
root@127.0.0.1 : test【10:58:35】19 SQL->select * from test_scheduler;
+---------+--------------------------------------+---------------------+
| sch_seq | sch_name                             | sch_createtime      |
+---------+--------------------------------------+---------------------+
|    1007 | 89aedcbc-db52-11e9-87ce-000c2929f2d3 | 2019-09-20 10:58:35 |
|    1008 | 917cd212-db52-11e9-aa58-000c29c345d6 | 2019-09-20 10:58:48 |
+---------+--------------------------------------+---------------------+
  1. 创建事件(主庫)
#每5秒调用一次 proc_test_scheduler()
DROP EVENT IF EXISTS even_test_scheduler;
CREATE EVENT IF NOT EXISTS even_test_scheduler
ON SCHEDULE EVERY 5 SECOND
DO call proc_test_scheduler();

19.1 创建事件(備庫)

#每6秒调用一次 proc_test_scheduler2()
DROP EVENT IF EXISTS even_test_scheduler2;
CREATE EVENT IF NOT EXISTS even_test_scheduler2
ON SCHEDULE EVERY 6 SECOND
DO call proc_test_scheduler2();

19.2 查詢事件狀態

#主庫(137)
root@127.0.0.1 : test【11:21:17】14 SQL->SELECT EVENT_SCHEMA,EVENT_NAME,EVENT_DEFINITION,INTERVAL_FIELD,STATUS,LAST_EXECUTED FROM information_schema.EVENTS\G
*************************** 1. row ***************************
    EVENT_SCHEMA: test
      EVENT_NAME: even_test_scheduler
EVENT_DEFINITION: call proc_test_scheduler()
  INTERVAL_FIELD: SECOND
          STATUS: ENABLED
   LAST_EXECUTED: 2019-09-20 11:22:53
*************************** 2. row ***************************
    EVENT_SCHEMA: test
      EVENT_NAME: even_test_scheduler2
EVENT_DEFINITION: call proc_test_scheduler2()
  INTERVAL_FIELD: SECOND
          STATUS: SLAVESIDE_DISABLED
   LAST_EXECUTED: NULL

#備庫(138)
root@127.0.0.1 : test【11:22:57】10 SQL->SELECT EVENT_SCHEMA,EVENT_NAME,EVENT_DEFINITION,INTERVAL_FIELD,STATUS,LAST_EXECUTED FROM information_schema.EVENTS\G
*************************** 1. row ***************************
    EVENT_SCHEMA: test
      EVENT_NAME: even_test_scheduler
EVENT_DEFINITION: call proc_test_scheduler()
  INTERVAL_FIELD: SECOND
          STATUS: SLAVESIDE_DISABLED
   LAST_EXECUTED: NULL
*************************** 2. row ***************************
    EVENT_SCHEMA: test
      EVENT_NAME: even_test_scheduler2
EVENT_DEFINITION: call proc_test_scheduler2()
  INTERVAL_FIELD: SECOND
          STATUS: ENABLED
   LAST_EXECUTED: 2019-09-20 11:23:57

20.事件總結

新创建的event在master上的状态是ENABLED,在slave上的状态是SLAVESIDE_DISABLED。
另外,在主库上修改event的status状态也不会改变slave上面的状态。

总结一下主从对event_scheduler的影响:
1. 在主库上新建event,在slave上event的状态为SLAVESIDE_DISABLED没有影响。
2. 通过xtrabackup恢复出来的从库,如果有events那么需要在slave上把event_scheduler设置为off,并且检查 events的status状态,如果是enable,则需要关闭事件调度器。
3. 当主从发生切换时,需要人工(或者有配套的机制)来维护event的状态。新主库
    
# 新主库
set global event_scheduler=on;
alter event e_insert enable;
 
# 新从库
set global event_scheduler=off;
alter event e_insert disable on slave;

4. 在主库上对event的进行状态修改不影响从库的状态。
上一篇下一篇

猜你喜欢

热点阅读