1. 程式人生 > 資料庫 >MySQL的SQL語句 -事務性語句和鎖定語句(3)- SAVEPOINT

MySQL的SQL語句 -事務性語句和鎖定語句(3)- SAVEPOINT

技術標籤:技術

一.MHA簡介

作者簡介


鬆信嘉範:
MySQL/Linux專家
2001年索尼公司入職
2001年開始使用oracle
2004年開始使用MySQL
2006年9月-2010年8月MySQL從事顧問
2010年-2012年 DeNA
2012年~至今 Facebook


軟體簡介

MHA能夠在較短的時間內實現自動故障檢測和故障轉移,通常在10-30秒以內;在複製框架中,MHA能夠很好地解決複製過程中的資料一致性問題,由於不需要在現有的replication中新增額外的伺服器,僅需要一個manager節點,而一個Manager能管理多套複製,所以能大大地節約伺服器的數量;另外,安裝簡單,無效能損耗,以及不需要修改現有的複製部署也是它的優勢之處。

MHA還提供線上主庫切換的功能,能夠安全地切換當前執行的主庫到一個新的主庫中(通過將從庫提升為主庫),大概0.5-2秒內即可完成。

MHA由兩部分組成:MHA Manager(管理節點)和MHA Node(資料節點)。MHA Manager可以獨立部署在一臺獨立的機器上管理多個Master-Slave叢集,也可以部署在一臺Slave上。當Master出現故障時,它可以自動將最新資料的Slave提升為新的Master,然後將所有其他的Slave重新指向新的Master。整個故障轉移過程對應用程式是完全透明的。

二.工作流程

1)把宕機的master二進位制日誌儲存下來。
2)找到binlog位置點最新的slave。

3)在binlog位置點最新的slave上用relay log(差異日誌)修復其它slave。
4)將宕機的master上儲存下來的二進位制日誌恢復到含有最新位置點的slave上。
5)將含有最新位置點binlog所在的slave提升為master。
6)將其它slave重新指向新提升的master,並開啟主從複製。

三.MHA架構圖

img

  • MHA manager 可以安裝在任意一臺伺服器上
  • 一個MHA manager可以管理多套mysql叢集(上百套)
  • 儘量避免安裝在主庫上(防止主庫斷點,斷網)
  • c\s結構的服務

四.MHA工具介紹

MHA軟體由兩部分組成,Manager工具包和Node工具包,具體的說明如下:

Manager工具包主要包括以下幾個工具:

masterha_check_ssh              #檢查MHA的ssh-key
masterha_check_repl             #檢查主從複製情況
masterha_manger                 #啟動MHA
masterha_check_status           #檢測MHA的執行狀態
masterha_master_monitor         #檢測master是否宕機
masterha_master_switch          #手動故障轉移
masterha_conf_host              #手動新增server資訊
masterha_secondary_check        #建立TCP連線從遠端伺服器
masterha_stop                   #停止MHA

Node工具包主要包括以下幾個工具:

cd /root/mha4mysql-node-0.56/bin
save_binary_logs                #儲存宕機的master的binlog
apply_diff_relay_logs           #識別relay log的差異
filter_mysqlbinlog              #防止回滾事件
purge_relay_logs                #清除中繼日誌

MHA優點總結

1)Masterfailover and slave promotion can be done very quickly
自動故障轉移快

2)Mastercrash does not result in data inconsistency
主庫崩潰不存在資料一致性問題

3)Noneed to modify current MySQL settings (MHA works with regular MySQL)
不需要對當前mysql環境做重大修改

4)Noneed to increase lots of servers
不需要新增額外的伺服器(僅一臺manager就可管理上百個replication)

5)Noperformance penalty
效能優秀,可工作在半同步複製和非同步複製,當監控mysql狀態時,僅需要每隔N秒向master傳送ping包(預設3秒),所以對效能無影響。你可以理解為MHA的效能和簡單的主從複製框架效能一樣。

ping baidu.com 10.0.0.50(icmp)
sql ping
select ping 檢測主庫的心跳

6)Works with any storage engine
只要replication支援的儲存引擎,MHA都支援,不會侷限於innodb

MySQL環境準備

1)環境檢查

mysql-db01

#系統版本
[[email protected] ~]# cat /etc/redhat-release 
CentOS release 6.7 (Final)
#核心版本
[[email protected] ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[[email protected] ~]# hostname -I
10.0.0.51

mysql-db02

#系統版本
[[email protected] ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
#核心版本
[[email protected] ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[[email protected] ~]# hostname -I
10.0.0.52

mysql-db03

#系統版本
[[email protected] ~]# cat /etc/redhat-release 
CentOS release 6.7 (Final)
#核心版本
[[email protected] ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[[email protected] ~]# hostname -I
10.0.0.53

安裝MySQL

1)安裝包準備

#建立安裝包存放目錄
[[email protected] ~]# mkdir /home/oldboy/tools -p
#進入目錄
[[email protected] ~]# cd /home/oldboy/tools/
#上傳mysql安裝包(mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz)
[[email protected] tools]# rz -be

2)安裝

#建立安裝目錄
[[email protected] tools]# mkdir /application
#解壓mysql二進位制包
[[email protected] tools]# tar xf mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz
#移動安裝包
[[email protected] tools]# mv mysql-5.6.16-linux-glibc2.5-x86_64 /application/mysql-5.6.16
#做軟連結
[[email protected] tools]# ln -s /application/mysql-5.6.16/ /application/mysql
#建立mysql使用者
[[email protected] tools]# useradd mysql -s /sbin/nologin -M
#進入mysql初始化目錄
[[email protected] tools]# cd /application/mysql/scripts/
#初始化mysql
[[email protected] scripts]# ./mysql_install_db \
--user=mysql \
--datadir=/application/mysql/data/ \
--basedir=/application/mysql/
#註解
--user:  指定mysql使用者
--datadir:指定mysql資料存放目錄
--basedir:指定mysql base目錄
#拷貝mysql配置檔案
[[email protected] ~]# \cp /application/mysql/support-files/my-default.cnf /etc/my.cnf
#拷貝mysql啟動指令碼
[[email protected] ~]# cp /application/mysql/support-files/mysql.server /etc/init.d/mysqld
#修改mysql預設安裝目錄(否則無法啟動)
[[email protected] ~]# sed -i 's#/usr/local#/application#g' /etc/init.d/mysqld
[[email protected] ~]# sed -i 's#/usr/local#/application#g' /application/mysql/bin/mysqld_safe
#配置mysql環境變數
[[email protected] ~]# echo 'export PATH="/application/mysql/bin:$PATH"' >> /etc/profile.d/mysql.sh
#重新整理環境變數
[[email protected] ~]# source /etc/profile
2.2.3啟動
#加入開機自啟
[[email protected] ~]# chkconfig mysqld on
#啟動mysql
[[email protected] ~]# /etc/init.d/mysqld start
Starting MySQL........... SUCCESS! #啟動成功
2.2.4配置密碼
#配置mysql密碼為oldboy123
[[email protected] ~]# mysqladmin -uroot password oldboy123

五.基於GTID的主從複製

GTID:全域性唯一識別符號,由UUID+TID,TID是事務提交編號,提交一個事務+1

342a3b8f-0d8e-11ea-8095-000c29c7dac3:1
342a3b8f-0d8e-11ea-8095-000c29c7dac3:2
342a3b8f-0d8e-11ea-8095-000c29c7dac3:23

先決條件
1)主庫和從庫都要開啟binlog
2)主庫和從庫server-id不同
3)要有主從複製使用者

GTID優點:

(1).支援多執行緒複製:事實上是針對每個database開啟相應的獨立執行緒,即每個庫有一個單獨的(sql

thread).

(2).支援啟用GTID,在配置主從複製,傳統的方式裡,你需要找到binlog和POS點,然後change master to指向. 在

mysql5.6裡,無須再知道binlog和POS點,只需要知道master的IP/埠/賬號密碼即可,因為同步複製是自動的,MySQL通

過內部機制GTID自動找點同步.(show master status)

(3).基於Row複製只儲存改變的列,大大節省Disk Space/Network resources和Memory usage.

(4).支援把Master 和Slave的相關資訊記錄在Table中 原來是記錄在檔案裡,記錄在表裡,增強可用性

(5).支援延遲複製

缺點:

  • mysqldump備份起來很麻煩,需要額外加引數,--set-gtid=on
  • 如果只從複製遇到了錯誤,s起來停了.跳過錯誤,gtid無法跳過錯誤

主庫操作

修改配置檔案

#編輯mysql配置檔案
[[email protected] ~]# vim /etc/my.cnf
#在mysqld標籤下配置
[mysqld]
#主庫server-id為1,從庫不等於1
server_id =1
#開啟binlog日誌
log_bin=mysql-bin

建立主從複製使用者

#登入資料庫
[[email protected] ~]# mysql -uroot -poldboy123
#建立rep使用者
mysql> grant replication slave on *.* to [email protected]'10.0.0.%' identified by 'oldboy123';

從庫操作

修改配置檔案

#修改mysql-db02配置檔案
[[email protected] ~]# vim /etc/my.cnf
#在mysqld標籤下配置
[mysqld]
#主庫server-id為1,從庫必須大於1
server_id =5
#開啟binlog日誌
log_bin=mysql-bin
#重啟mysql
[[email protected] ~]# /etc/init.d/mysqld restart
#修改mysql-db03配置檔案
[[email protected] ~]# vim /etc/my.cnf
#在mysqld標籤下配置
[mysqld]
#主庫server-id為1,從庫必須大於1
server_id =10
#開啟binlog日誌
log_bin=mysql-bin
#重啟mysql
[[email protected] ~]# /etc/init.d/mysqld restart

注:在以往如果是基於binlog日誌的主從複製,則必須要記住主庫的master狀態資訊。

mysql> show master status;
+------------------+----------+
| File             | Position |
+------------------+----------+
| mysql-bin.000002 |      120 |
+------------------+----------+

開啟GTID

#沒開啟之前先看一下GTID的狀態
mysql> show global variables like '%gtid%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| enforce_gtid_consistency | OFF   |
| gtid_executed            |       |
| gtid_mode                | OFF   |
| gtid_owned               |       |
| gtid_purged              |       |
+--------------------------+-------+ 
#編輯mysql配置檔案(主庫從庫都需要修改)
[[email protected] ~]# vim /etc/my.cnf
#在[mysqld]標籤下新增
[mysqld]
gtid_mode=ON
log_slave_updates #保持binlog重新整理
enforce_gtid_consistency  
#重啟資料庫
[[email protected] ~]# /etc/init.d/mysqld restart
#檢查GTID狀態
mysql> show global variables like '%gtid%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| enforce_gtid_consistency | ON    | #執行GTID一致
| gtid_executed            |       |
| gtid_mode                | ON    | #開啟GTID模組
| gtid_owned               |       |
| gtid_purged              |       |
+--------------------------+-------+

log-slave-updates 什麼時候用

  • 雙主模式
  • 級聯複製
  • GTID

注:主庫從庫都需要開啟GTID否則在做主從複製的時候就會報錯:

[[email protected] ~]# mysql -uroot -poldboy123
mysql> change master to
-> master_host='10.0.0.51',
-> master_user='rep',
-> master_password='oldboy123',
-> master_auto_position=1;
ERROR 1777 (HY000): CHANGE MASTER TO MASTER_AUTO_POSITION = 1 can only be executed when @@GLOBAL.GTID_MODE = ON.

配置主從複製

#登入資料庫
[[email protected] ~]# mysql -uroot -poldboy123
#配置複製主機資訊
mysql> change master to
#主庫IP
-> master_host='10.0.0.51',
#主庫複製使用者
-> master_user='rep',
#主庫複製使用者的密碼
-> master_password='oldboy123',
#GTID位置點
-> master_auto_position=1;
#開啟slave
mysql> start slave;
#檢視slave狀態
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 403
               Relay_Log_File: mysql-db02-relay-bin.000002
                Relay_Log_Pos: 613
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          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: 403
              Relay_Log_Space: 822
              Until_Condition: None

六.部署MHA(前提已經做好主從,儘量不在主庫上安裝管理節點)

主庫

1.開啟binlog

2.開啟server_id

3.建立主從複製使用者

從庫

1.開啟binlog

2.開啟server_id:從庫與主庫之間的server_id不同即可, 從庫之間不可以相同

3.change master to

4.在做主從之前,要保證資料的一致性

5.從庫也要建立主從複製使用者

前提條件

#臨時關閉relay log(主庫和從庫)
set global relay_log_purge = 0;
# 臨時開啟 只讀(從庫)
set global read_only=1;
# 永久關閉自動刪除relay log(主庫和從庫)
relay_log_purge = 0

1)環境準備(所有節點)

# 安裝node和manager,必須要有epel
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# 安裝node節點(有幾臺資料庫就裝幾個node節點)
[[email protected] ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
# 每臺數據庫上都要建立 mha 管理使用者(主庫執行從庫會複製)
mysql> grant all on *.* to [email protected]'%' identified by 'mha';

命令軟連線(所有節點)

#如果不建立命令軟連線,檢測mha複製情況的時候會報錯
[[email protected] ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[[email protected] ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

部署管理節點(mha-manager:mysql-db03)

#安裝manager包
[[email protected] tools]# rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm 
Preparing...              ########################################### [100%]
1:mha4mysql-manager       ########################################### [100%]

編輯配置檔案

#建立配置檔案目錄
[[email protected] ~]# mkdir -p /etc/mha
#建立日誌目錄
[[email protected] ~]# mkdir -p /etc/mha/app1
#編輯mha配置檔案
[[email protected] ~]# vim /etc/mha/app1.cnf
# 修改配置檔案
[server default]
#MHA日誌名字
manager_log=/etc/mha/manager.log
#MHA的工作目錄
manager_workdir=/etc/mha/app1
#資料庫binlog存放路徑
master_binlog_dir=/application/mysql/data
#mha管理使用者的使用者名稱
user=mha
#mha管理使用者的密碼
password=mha
#監測心跳,每隔2秒監測一次(預設是3秒)
ping_interval=2
#主從複製使用者的密碼
repl_password=123
#主從複製使用者
repl_user=slave
#ssh遠端連線使用者(做完免密的)
ssh_user=root
[server1]
hostname=10.0.0.51
port=3306
[server2]
hostname=10.0.0.52
port=3306
ssh 免密認證
MHA監測啟動
[server3]
hostname=10.0.0.53
port=3306
[server4]
hostname=10.0.0.54
port=3306

配置檔案詳解

[server default]
#設定manager的工作目錄
manager_workdir=/var/log/masterha/app1
#設定manager的日誌
manager_log=/var/log/masterha/app1/manager.log 
#設定master 儲存binlog的位置,以便MHA可以找到master的日誌,我這裡的也就是mysql的資料目錄
master_binlog_dir=/data/mysql
#設定自動failover時候的切換指令碼
master_ip_failover_script= /usr/local/bin/master_ip_failover
#設定手動切換時候的切換指令碼
master_ip_online_change_script= /usr/local/bin/master_ip_online_change
#設定mysql中root使用者的密碼,這個密碼是前文中建立監控使用者的那個密碼
password=123456
#設定監控使用者root
user=root
#設定監控主庫,傳送ping包的時間間隔,嘗試三次沒有迴應的時候自動進行failover
ping_interval=1
#設定遠端mysql在發生切換時binlog的儲存位置
remote_workdir=/tmp
#設定複製使用者的密碼
repl_password=123456
#設定複製環境中的複製使用者名稱 
repl_user=rep
#設定發生切換後傳送的報警的指令碼
report_script=/usr/local/send_report
#一旦MHA到server02的監控之間出現問題,MHA Manager將會嘗試從server03登入到server02
secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 --master_port=3306
#設定故障發生後關閉故障主機指令碼(該指令碼的主要作用是關閉主機放在發生腦裂,這裡沒有使用)
shutdown_script=""
#設定ssh的登入使用者名稱
ssh_user=root 

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306
#設定為候選master,如果設定該引數以後,發生主從切換以後將會將此從庫提升為主庫,即使這個主庫不是叢集中事件最新的slave。
candidate_master=1
#預設情況下如果一個slave落後master 100M的relay logs的話,MHA將不會選擇該slave作為一個新的master,因為對於這個slave的恢復需要花費很長時間,通過設定check_repl_delay=0,MHA觸發切換在選擇一個新的master的時候將會忽略複製延時,這個引數對於設定了candidate_master=1的主機非常有用,因為這個候選主在切換的過程中一定是新的master
check_repl_delay=0

配置ssh信任(所有節點)

#建立祕鑰對
[[email protected] ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
#傳送公鑰,包括自己
[[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]
[[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]
[[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]

啟動測試

#測試ssh
[[email protected] ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
#看到如下字樣,則測試成功
Tue Mar  7 01:03:33 2017 - [info] All SSH connection tests passed successfully.
#測試複製
[[email protected] ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
#看到如下字樣,則測試成功
MySQL Replication Health is OK.

啟動MHA

#啟動
[[email protected] ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

#測試啟動是否成功
[[email protected] scripts]# masterha_check_status --conf=/etc/mha/app1.cnf 
app1 (pid:7916) is running(0:PING_OK), master:10.0.0.51

切換master測試

#登入資料庫(db02)
[[email protected] ~]# mysql -uroot -poldboy123
#檢查複製情況
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 191
               Relay_Log_File: mysql-db02-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
#登入資料庫(db03)
[[email protected] ~]# mysql -uroot -poldboy123
#檢查複製情況
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 191
               Relay_Log_File: mysql-db03-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

#停掉主庫
[[email protected] ~]# /etc/init.d/mysqld stop
Shutting down MySQL..... SUCCESS!
#登入資料庫(db02)
[[email protected] ~]# mysql -uroot -poldboy123
#檢視slave狀態
mysql> show slave status\G
#db02的slave已經為空
Empty set (0.00 sec)
#登入資料庫(db03)
[[email protected] ~]# mysql -uroot -poldboy123
#檢視slave狀態
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 191
               Relay_Log_File: mysql-db03-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

mha恢復(傳統的)

#1.恢復舊主庫
[[email protected] ~]# /etc/init.d/mysqld start
Starting MySQL SUCCESS! 

#2.在mha日誌中找到change master to
[[email protected] ~]# grep -i 'change master to' /etc/mha/manager.log 
Tue Nov 19 20:50:57 2019 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='slave', MASTER_PASSWORD='xxx';
Wed Nov 20 03:29:19 2019 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=120, MASTER_USER='slave', MASTER_PASSWORD='xxx';

#3.在舊主庫中執行change master語句
CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=120, MASTER_USER='slave', MASTER_PASSWORD='xxx';

#4.將mha配置檔案修復
[server1]
hostname=10.0.0.51
port=3306

#5.啟動mha
[[email protected] ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --
ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &

[[email protected] ~]# masterha_check_status --conf=/etc/mha/app1.cnf 
#MHA啟動命令 詳解
nohup masterha_manager
#配置檔案路徑
--conf=/etc/mha/app1.cnf
#從配置檔案中移除主庫
--remove_dead_master_conf
#忽略上次切換
--ignore_last_failover 
< /dev/null > /etc/mha/manager.log 2>&1 &
#mha工作機制:在mha一次切換後,會在mha的工作目錄下生成一個lock,鎖檔案

注意:重新切換後,再次啟動mha

指令碼恢復

#分別放在每個node節點服務下
[[email protected] ~]# vim abc.sh 

#!/bin/bash
/etc/init.d/mysqld start
change=`ssh 10.0.0.54 "grep -i 'change master to' /etc/mha/manager.log"|awk -F : '{print $4}'|sed 's#xxx#123#g'`
mysql -e "$change;start slave;"
ssh 10.0.0.54 \cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf

MHA切換

如果在資料量相同的情況下,根據server標籤,越小優先順序越高

七.配置VIP漂移

VIP漂移的兩種方式
1)通過keepalived的方式,管理虛擬IP的漂移
2)通過MHA自帶指令碼方式,管理虛擬IP的漂移

MHA指令碼方式

修改配置檔案

#編輯配置檔案
[[email protected] ~]# vim /etc/mha/app1.cnf
#在[server default]標籤下新增
[server default]
#使用MHA自帶指令碼
master_ip_failover_script=/usr/local/bin/master_ip_failover

編輯指令碼

#修改ssh埠.配置檔案APP1.cnf和/etc/mha/master_ip_failover都要新增


#根據配置檔案中指令碼路徑編輯
[[email protected] ~]# vim /etc/mha/master_ip_failover
#修改以下幾行內容
my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down"; 
#新增執行許可權,否則mha無法啟動
[[email protected] ~]# chmod +x /etc/mha/master_ip_failover
#語法問題
#格式問題
yum -y install dos2unix
[[email protected] mha]# dos2unix master_ip_failover
dos2unix: converting file master_ip_failover to Unix format ...

手動繫結VIP

#繫結vip
[[email protected] ~]# ifconfig eth0:0 10.0.0.55/24
#宕掉
ifconfig eth0:0 down
#檢視vip
[[email protected] ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
   inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

測試ip漂移

#登入db02
[[email protected] ~]# mysql -uroot -poldboy123
#檢視slave資訊
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000007
          Read_Master_Log_Pos: 191
               Relay_Log_File: mysql-db02-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000007
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
#停掉主庫
[[email protected] ~]# /etc/init.d/mysqld stop
Shutting down MySQL..... SUCCESS!
#在db03上檢視從庫slave資訊

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 191
               Relay_Log_File: mysql-db03-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
#在db01上檢視vip資訊
[[email protected] ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
#在db02上檢視vip資訊
[[email protected] ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

出現腦裂

1.停止vip
2.重新做從庫指向 
預防:
停庫檢查mha配置檔案是否補全,沒有,補全,啟動mha

測試動點vip漂移

一、建立建表語句
=============================================
學生表:Student(Sno,Sname,Ssex,Sage,Sdept)
------(學號-主鍵,姓名,性別,年齡,所在系)
=============================================

create table student(
Sno int(10) NOT NULL COMMENT '學號',
Sname varchar(16) NOT NULL COMMENT '姓名',
Ssex char(2) NOT NULL COMMENT '性別',
Sage tinyint(2)  NOT NULL default '0' COMMENT '學生年齡',
Sdept varchar(16)  default NULL  COMMENT '學生所在系別', 
PRIMARY KEY  (Sno) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

二、批量插入資料指令碼
#!/bin/bash
MysqlLogin="mysql -uroot -p123"
i=1
while true
do
 ${MysqlLogin} -e "insert into test.student values ("$I",'zls"$i"','m','21','computer"$i"');"
 ((i++))
 sleep 2;
done

八.配置binlog-server

修改mha配置檔案

[[email protected] ~]# vim /etc/mha/app1.cnf
[binlog1]
no_master=1
hostname=10.0.0.54         #主庫
master_binlog_dir=/data/mysql/binlog/

備份binlog

#建立備份binlog目錄
[[email protected] ~]# mkdir -p /data/mysql/binlog/
#進入該目錄
[[email protected] ~]# cd /data/mysql/binlog/
#備份binlog(進入創鍵目錄下)
[[email protected] binlog]# mysqlbinlog  -R --host=10.0.0.51 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &
#啟動mha
[[email protected] binlog]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &

測試binlog備份

#檢視binlog目錄中的binlog
[[email protected] binlog]# ll
total 44
-rw-r--r-- 1 root root 285 Mar  8 03:11 mysql-bin.000001
#登入主庫
[[email protected] ~]# mysql -uroot -poldboy123
#重新整理binlog
mysql> flush logs;
#再次檢視binlog目錄
[[email protected] binlog]# ll
total 48
-rw-r--r-- 1 root root 285 Mar  8 03:11 mysql-bin.000001
-rw-r--r-- 1 root root 143 Mar  8 04:00 mysql-bin.000002

九.MySQL中介軟體Atlas

Atlas簡介

Atlas是由 Qihoo 360公司Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的資料中間層專案。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了很多功能特性。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了很多功能特性。

Atlas主要功能


  • 1.讀寫分離
  • 2.從庫負載均衡
  • 3.IP過濾
  • 4.自動分表
  • 5.DBA可平滑上下線DB
  • 6.自動摘除宕機的DB

Atlas相對於官方MySQL-Proxy的優勢


  • 1.將主流程中所有Lua程式碼用C重寫,Lua僅用於管理介面
  • 2.重寫網路模型、執行緒模型
  • 3.實現了真正意義上的連線池
  • 4.優化了鎖機制,效能提高數十倍

安裝Atlas

同學們有福了,安裝Atlas真的是炒雞簡單,官方提供的Atlas有兩種:

1)Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm
2)Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm

這裡我們只需要下載普通的即可。

#在主庫安裝,進入安裝包目錄
[[email protected] ~]# cd /home/oldboy/tools/
#下載Atlas
[[email protected] tools]# 
wget httpss://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
#安裝
[[email protected] tools]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm 
Preparing...               ########################################### [100%]
  1:Atlas                  ########################################### [100%]

編輯配置檔案

#進入Atlas工具目錄
[[email protected] ~]# cd /usr/local/mysql-proxy/bin/
#生成密碼
[[email protected] bin]# ./encrypt oldboy123
#修改Atlas配置檔案
[[email protected] ~]# vim /usr/local/mysql-proxy/conf/test.cnf #(instance = test)

#Atlas後端連線的MySQL主庫的IP和埠,可設定多項,用逗號分隔
proxy-backend-addresses = 10.0.0.51:3306
#Atlas後端連線的MySQL從庫的IP和埠
proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306
#使用者名稱與其對應的加密過的MySQL密碼
pwds = root:1N/CNLSgqXuTZ6zxvGQr9A==
#SQL日誌的開關
sql-log = ON
#Atlas監聽的工作介面IP和埠
proxy-address = 0.0.0.0:3307
#預設字符集,設定該項後客戶端不再需要執行SET NAMES語句
charset = utf8

啟動Atlas

[[email protected] ~]# /usr/local/mysql-proxy/bin/mysql-proxyd test start
OK: MySQL-Proxy of test is started

Atlas管理介面操作

#用atlas管理使用者登入
[[email protected] ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345
#檢視可用命令幫助
mysql> select * from help;
#檢視後端代理的庫
mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.51:3307 | up    | rw   |
|           2 | 10.0.0.53:3307 | up    | ro   |
|           3 | 10.0.0.52:3307 | up    | ro   |
+-------------+----------------+-------+------+
#平滑摘除mysql
mysql> REMOVE BACKEND 2;
Empty set (0.00 sec)
#檢查是否摘除成功
mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.51:3307 | up    | rw   |
|           2 | 10.0.0.52:3307 | up    | ro   |
+-------------+----------------+-------+------+
#儲存到配置檔案中
mysql> SAVE CONFIG;
Empty set (0.06 sec)
mysql>  select * from help;
+----------------------------+---------------------------------------------------------+
| command                    | description                                             |
+----------------------------+---------------------------------------------------------+
| SELECT * FROM help         | shows this help                                         |
| SELECT * FROM backends     | 檢視後端的伺服器狀態                                      |
| SET OFFLINE $backend_id    | 平滑下線 例如:set offline 2;                               |
| SET ONLINE $backend_id     | 平滑上線 例如:set online 2;                             |
| ADD MASTER $backend        | 新增後端主庫:add master 10.0.0.56:3306               |
| ADD SLAVE $backend         | 新增後端從庫:add slave 10.0.0.56:3306;                |
| REMOVE BACKEND $backend_id | 刪除後端節點: remove backend 1;                        |
| SELECT * FROM clients      | 檢視允許連線的客戶端IP                                       |
| ADD CLIENT $client         | 新增客戶端IP:add client 10.0.0.51;                  |
| REMOVE CLIENT $client      | 刪除客戶端IP:remove client 10.0.0.51               |
| SELECT * FROM pwds         | 檢視後端資料庫的使用者和密碼                                          |
| ADD PWD $pwd               | 新增使用者,自動加密:add pwd root:123               |
| ADD ENPWD $pwd             | 新增使用者,需要手動加密後的密碼       |
| REMOVE PWD $pwd            | 刪除沒有用的使用者:remove pwd xxx;                         |
| SAVE CONFIG                | 儲存到配置檔案                       |
| SELECT VERSION             | 檢視版本                            |
+----------------------------+---------------------------------------------------------+

補充:傳統做法

主配:
[[email protected] scripts]# cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server_id=1
#gtid_mode=on
#log-slave-updates
#enforce_gtid_consistency
#relay_log_purge = 0
skip_name_resolve
relay_log_purge = 0

從配:
[[email protected] scripts]# cat /etc/my.cnf
[mysqld]
server_id=2
#gtid_mode=on
log-bin=mysql-bin
#log-slave-updates
#enforce_gtid_consistency
#relay_log_purge = 0
skip_name_resolve

#管理節點:注意擋掉之後節點就沒了,需新增
[[email protected] scripts]# vim /etc/mha/app1.cnf 

[server default]
manager_log=/etc/mha/manager.log                                                                               
manager_workdir=/etc/mha/app1
master_binlog_dir=/application/mysql/data
password=mha
ping_interval=2
repl_password=123
repl_user=slave
ssh_user=root
user=mha

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306

[server4]
hostname=10.0.0.54
port=3306

vip漂移,atlas

node節點自動恢復從庫指令碼

[[email protected] ~]# cat abc.sh 
#!/bin/bash
/etc/init.d/mysqld start
change=`ssh 10.0.0.54 "grep -i 'change master to' /etc/mha/manager.log"|awk -F : '{print $4}'|sed 's#xxx#123#g'`
mysql -e "$change;start slave;"

管理節點呼叫指令碼實現非互動,實現VIP漂移

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

my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
'''



sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;

    `ssh $ssh_user\@$orig_master_host \" sh /root/abc.sh \"`;
}
sub stop_vip() {

     return 0  unless  ($ssh_user);
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
'''

實現atlas管理資料庫指令碼

[[email protected] mha]# vim  /root/cre.sh 

#!/bin/bash
while true;do
        succ=`sed -nr 's#^Master.*ted (.*)\.$#\1#gp' /etc/mha/manager.log`
        if [[ $succ == 'successfully' ]];then
                \cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf
                down_master=`sed -nr 's#^Master (.*)\(.*down\!#\1#gp' /etc/mha/manager.log`
                new_master=`sed -rn 's#^Master .*\((.*)\) completed.*#\1#gp' /etc/mha/manager.log`

                new_master_num=`mysql -uuser -ppwd -h127.0.0.1 -P2345 -e 'select * from backends;'|grep '$new_master' |awk '{print $1}'`
                
                
               mysql -uuser -ppwd -h127.0.0.1 -P2345 -e "remove backend ${new_master_num};save config;"
                
               mysql -uuser -ppwd -h127.0.0.1 -P2345 -e "add slave  ${down_master}:3306;save config;"

               nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 & 
        else
                echo "$(date +%F-%T) MHA沒有切換" > /etc/mha/app1.log
                sleep 2
        fi
done