一、mysql複製
1、mysql複製
MySQL複製是指從一個MySQL主實例服務器(master)將數據複製到另一臺或多臺MySQL從從實例服務器(slaves)的過程。MySQL複製的數據粒度可以是主實例上所有的數據庫,也可以是指定的一個或多個數據庫,也可以是一個數據庫裏的指定的表。默認複製操作是異步進行的,salves服務器不需要持續的保持連接接受master服務器的數據。
2、mysql複製的作用
(1)擴展能力:通過複製功能可以將MySQL的性能壓力分擔到一個或多個slave實例上。
(2)數據庫備份:由於從實例是同步主實例的數據,所以可以將備份作業部署到從庫
(3)數據分析和報表:一些數據分析和報表的實現可以在從實例執行,以減少對主庫的性能影響
(4)容災能力:異地同步,提升容災能力
3、mysql複製的方法
(1)傳統方式:基於主庫的bin-log將日誌事件和事件位置複製到從庫,從庫再加以應用來達到主從同步的目的
(2)Gtid方式:global transaction identifiers是基於事務來複制數據,因此也就不依賴日誌文件,同時又能更好的保證主從庫數據一致性
4、複製的類型
(1)異步複製:一個主庫,一個或多個從庫,數據異步同步到從庫
(2)同步複製:在MySQL Cluster中特有的複製方式
(3)半同步複製:在異步複製的基礎上,確保任何一個主庫上的事務在提交之前至少有一個從庫已經收到該事務並日志記錄下來
(4)延遲複製:在異步複製的基礎上,人爲設定主庫和從庫的數據同步延遲時間,即保證數據延遲至少是這個參數
5、mysql複製的模式
(1)基於語句的複製(statement based replication):基於主庫將SQL語句寫入到bin log中完成複製
優勢:1)技術比較成熟,應用廣泛
2)使用語句複製節省空間
3)可以用來做審計功能(該二進制文件中包含了所有的語句)
缺點:某些特定的修改語句在複製時會有問題(一些存儲過程和函數)
(2)基於行數據的複製(row based replication):基於主庫將每一個行數據變化的信息作爲事件寫入到bin log中完成日誌。
優勢:1)所有的數據庫修改都可以被複制,是一種安全的方式
2)由於是行復制,所以某些語句在主庫和從庫上執行需要較少的lock
缺點:1)DML語句涉及到多行的修改時,導致bin log會很大
2)不能直接查看在備庫中執行的SQL語句
(3)混合複製(mixed based replication):上述兩者的結合。默認情況下優先使用基於語句的複製,只有當部分語句如果基於語句複製不安全的情況下才會自動切換爲基於行數據的複製
6、主從複製時的線程
(1)binlog dump thread:在主庫創建,用來在從庫連接過來時發送bin log的內容
(2)slave io thread:在備庫創建,用來連接主庫並請求發送新的bin log內容。該線程讀取主庫的bin log dump線程發送的更新內容並將此內容複製到本地的relay log中
(3)Slave sql thread:在備庫創建,讀取slave io線程在本地relay log中的內容並在本地執行內容中的事件
二、mysql基於bin-log日誌的複製
1、mysql複製的原理
在主庫的二進制日誌裏記錄了對數據庫的變更,從庫從主庫那裏獲取日誌,然後在從庫中重放這部分日誌,從而實現數據的同步
2、複製步驟
(1)主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。
(2)從庫複製主庫的二進制日誌事件到本地的中繼日誌(relay log)。
(3)從庫重放中繼日誌。
3、複製配置
(1)配置複製前主備工作
在複製前需準備好主庫和從庫並在主庫創建一個專門用來做複製的數據庫用戶,並確保這個用戶有複製的權限。
主機地址 |
功能 |
執行復制的用戶 |
Mysql版本 |
192.168.16.151 |
主庫 |
repl |
5.7.23 |
192.168.16.152 |
從庫 |
|
5.7.23 |
# 在主庫上創建用於複製的用戶
mysql> CREATE USER 'repl'@'192.168.16.%' IDENTIFIED BY 'replication';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.16.%';
(2)配置主庫
在複製前主庫需要開啓bin-log,並且指定一個唯一的server-id,配置完成後重啓數據庫;同時也要確保配置文件中skip-networking參數爲非開啓狀態,否則會導致主從庫不能通信而複製失敗。
在同一個複製組下的所有實例的server_id都必須是唯一的,而且取值必須是正整數,取值範圍是1~(232)−1。
# 配置主庫的server-id及開啓binglog,配置完成後需要重啓mysql
[mysqld]
log-bin=mysql-bin
server-id=1
# 重啓後查看log_bin的狀態
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/data/mysql-bin |
| log_bin_index | /data/mysql/data/mysql-bin.index |
(3)獲取主庫的日誌信息
爲了確保建立的備庫能從正確的bin log位置開啓複製,要首先獲取主庫的bin log信息,包括當前的日誌文件名和日誌文件內的位置;在操作前需要鎖定主庫,直到獲取的big log位置前的日誌傳到從庫爲止。
# 鎖定所有的表,防止寫入
mysql> FLUSH TABLES WITH READ LOCK;
# 獲取當前日誌信息
mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
(4)將主庫當前的數據同步到從庫
複製建立前同步時可通過兩種方式實現:一種是用mysqldump命令實現(innodb存儲引擎推薦的方式);另一種是把主庫臨時關閉,將數據文件從主庫拷貝到從庫,這種方式效率更高(省去了dump/import過程中insert語句執行導致的更新index的行爲)。
# 將主庫上的數據導出並傳到從庫
~]# mysqldump --all-databases --master-data -u root -p > dbdump.db
~]# scp dbdump.db [email protected]:/data/mysql/data
# 在主庫上釋放鎖
mysql> unlock tables;
(5)配置從庫並在從庫上導入數據
從庫上也需要配置唯一server-id,bin log屬性可以可以更具自己的需要可打開卡不打開。
# 配置從庫的server-id並重啓重庫
[mysqld]
server-id=2
從庫配置完成後需要將從主庫到處的數據在從庫導入。
# 在從庫上導入主庫導出的數據
]# mysql -uroot -p </data/mysql/data/dbdump.db
(6)在從庫上配置主庫信息並導入數據
在上面配置完成後就可以在從庫上配置主庫的相關信息,並通過”start slave”命令啓動複製功能,在從庫上需要配置主庫的一下信息:
MASTER_HOST=’master_host_name’:主庫的主機名
MASTER_PORT=port_number:主庫的端口號
MASTER_USER=’replication_user_name’:複製的數據庫用戶名
MASTER_PASSWORD=’replication_password’:複製的用戶密碼
MASTER_LOG_FILE=’recorded_log_file_name’:主庫的日誌文件名 MASTER_LOG_POS=recorded_log_position:主庫的日誌文件位置
# 登錄從庫配置與主庫相關的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_PORT=3306,
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.41 sec)
# 啓動主從複製
mysql> start slave;
Query OK, 0 rows affected (0.05 sec)
(7)查看複製是否正常
# 在從庫上查看複製是否正常
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.16.151
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 474
... .. .
(8)一主多從環境的配置
在創建從庫時可以同時創建多個從庫,如果當前的主從環境啓動後還想添加主從,則可以直接使用先前使用的備份文件及主庫的狀態建立主從複製 。
# 修改第三臺mysql數據庫的server-id並重啓
[mysqld]
server-id=3
# 將主庫的備份文件複製過來並導入
~]# scp [email protected]:/data/dbdump2.db ./
~]# mysql -uroot -p <dbdump2.db
# 登錄當前從庫配置與主庫相關的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_PORT=3306,
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
# 啓動複製
mysql> start slave;
# 查看複製狀態
mysql> show slave status\G
如果再增加從庫時,爲了減輕主庫的壓力,也可設置讓複製從當前建立好的從庫中去複製數據。
4、複製模式的配置
(1)基於語句的複製的配置
基於語句的複製在主庫的配置文件中添加以下內容:
# 基於語句複製的配置
binlog-format=statement
(2)基於行復制的配置
基於行的複製在主庫的配置文件中添加以下內容:
# 基於行的二進制文件的複製
binlog-format=row
# 查看當前數據庫的複製方式
mysql> show variables like '%format%';
+---------------------------+-------------------+
| Variable_name | Value |
+---------------------------+-------------------+
| binlog_format | ROW |
三、mysql基於GTID的複製
1、GTID複製
GTID複製是完全基於事務的複製,即每個在主庫上執行的事務都會被分配一個唯一的全局ID並記錄和應用在從庫上,這種複製方式簡化了建立slave和master之間切換的工作,因爲其完全不需要找當前執行的bin log和log中的位置完成切換。
一個GTID是master上執行的任何commit事務所分配的全局唯一ID標示,其由兩部分組成:GTID = source_id:transaction_id;Source_id代表主庫的server_uuid,transaction_id代表事務按順序提交的ID。
2、GTID的複製過程
(1)當一個事務在主庫提交時,該事務就被賦予了一個GTID,並記錄在主庫的binary log
(2)主庫的binary log會被傳輸到從庫的relay log中,從庫讀取此GTID並生成gtid_next系統參數
(3)從庫驗證此GTID並沒有在自己的binary log中使用,則應用此事務在從庫上
3、配置主庫及從庫,將之前的基於bin-log複製改爲GTID複製
5.6版本中的GTID複製模式,slave必須開啓bin-log和log_slave_updates參數,否則啓動就報錯,因爲需要在binlog找到同步複製的信息(UUID:事務號);5.7版本中, gtid_executed系統表記錄同步複製的信息(UUID:事務號),這樣就不用開啓log_slave_updates參數,減少了從庫的壓力。
# 設置主庫及從庫爲只讀模式
mysql> SET @@global.read_only = ON;
# 關閉主庫及從庫
[root@localhost ~]# mysqladmin -uroot -p shutdown
# 在主庫及從庫配置中添加以下配置文件並啓動主從兩個實例
gtid-mode=on
#確保只有對gtid複製機制安全的語句纔會被log
enforce-gtid-consistency=on
skip-slave-start=1
# 在從庫上從新配置主從複製關係並啓動slave進程
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_AUTO_POSITION=1;
mysql> start slave;
# 關閉主庫及從庫的read only模式
mysql> SET @@global.read_only = OFF;
# 在從庫上查看主從複製的狀態
mysql> show slave status\G
4、使用GTID複製的制約條件
(1)當master和slave的表使用的存儲引擎不一樣時,會導致GTID複製功能不正常
(2)GTID複製不支持create table … select語句
(3)create/drop temporary table語句在GTID複製環境中不能放在事務中執行,只能單獨執行,並且autocommit要開啓
(4)sql_slave_skip_counter語句是不支持的,如果想要跳過事務,可以使用gtid_executed變量
四、mysql複製時使用的參數及查看複製狀態
1、mysql複製時的參數
(1)server_id:是必須設置在master和每個slave上的唯一標識ID,其取值範圍是1~4294967295之間,且同一個複製組之內不能重複
(2)server_uuid:server_uuid會在GTID複製中使用。當MySQL啓動之後,會首先到數據文件目錄下的auto.cnf中尋找是否有指定的server_uuid,如果沒有找到,則自己生成一個server_uuid並保存到這個文件中
(3)log_slave_updates:該參數用來控制是否將收到的主庫的更新數據的語句也記錄在slave自己的bin log中
(4)relay-log:該參數用來指定relay-log文件的基礎名稱,默認的名稱爲host_name-relay-bin.xxxx
(5)replicate-do-db:該參數用來指定需要複製的數據庫,有多個數據庫需要複製,則這個參數要使用多次。
(6)replicate-ignore-db:該參數決定了忽略指定數據庫的複製
(7)replicate-do-table=db_name.tbl_name:通過該參數告知slave的SQL thread僅複製指定表上的數據。如果有多個表,則該參數要使用多次
(8)replicate-ignore-table=db_name.tbl_name:通過該參數告知slave的SQL thread將指定表上的數據過濾掉
(9)replicate-wild-do-table=db_name.tbl_name:通過該參數告知SQL的SQL thread僅複製符合匹配的表,可以使用_和%作爲通配符
(10)replicate-wild-ignore-table=db_name.tbl_name:通過該參數告知SQL的SQL thread過濾掉符合匹配的表。
(11)slave-parallel-workers: 該參數決定了slave上啓動多個SQL thread線程來並行應用數據的。默認值是0代表不允許並行,取值範圍可以是0~1024
(12)skip-slave-start :該參數決定了在MySQL啓動時是否先不啓動slave線程,即暫停複製
(13)slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]:該參數決定了當slave的SQL thread執行過程中碰到何種錯誤時可以忽略並繼續接下來的數據複製
(14)slave-parallel-type=type :該參數決定了當啓動了並行之後,採用什麼粒度的並行方式。默認值database表示按照不同的數據庫執行並行,LOGICAL_CLOCK則表示按照在binlog中的一組提交的事務作爲並行粒度
(15)sql_slave_skip_counter代表在非GTID複製環境下,通過設置此參數來跳過多少個複製事件。該參數會在下次執行start slave命令時生效
(16)log-bin[=base_name] :該參數表示是否開啓binary log
(17)binlog-do-db=db_name: 該參數決定了哪些庫下的修改會被記錄到bin log中。
(18)binlog-ignore-db=db_name:該參數決定了在bin log中忽略的數據庫
(19)binlog_format:該參數決定了bin log中記錄的格式,值有statement,row,mixed,分別代表基於SQL語句的複製,基於行復制和基於混合複製。
2、複製狀態的查看
在主庫可以通過執行show processlist命令查看主庫的bin log日誌生成進程;在從庫上可以通過執行”show slave status”來檢查複製是否正常工作,主要的參數說明如下:
Slave_IO_State:代表當前slave的狀態 S
lave_IO_Running:代表負責讀取主庫bin log的IO線程的運行狀態
Slave_SQL_Running:代表負責執行備庫relay log的SQL線程的運行狀態
Last_IO_Error, Last_SQL_Error: 分別代表最後一次IO線程和SQL線程所發生的錯誤,沒有則爲空。
Seconds_Behind_Master:代表備庫的SQL線程比主庫的bin log晚多少秒
Master_Log_file, Read_Master_Log_Pos:表示IO線程在主庫bin log中的座標位置 Relay_Master_Log_File, Exec_Master_Log_Pos:表示SQL線程在主庫bin log中的座標位置
Relay_Log_File, Relay_Log_Pos:表示SQL線程在備庫relay log中的座標位置
五、延遲複製與半同步複製
1、延遲複製
延遲複製是指定從庫對主庫的延遲至少是指定的這個間隔時間,默認是0秒。可以通過” CHANGE MASTER TO MASTER_DELAY = N”命令來指定,其原理是從庫收到主庫的bin log之後,不是立即執行,而是等待指定的秒數之後再執行。
(1)配置延遲複製
# 在從庫上配置延遲複製,延遲90秒
mysql> stop slave;
mysql> CHANGE MASTER TO MASTER_DELAY = 60;
mysql> start slave;
# 查看複製狀態
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.16.151
…
SQL_Delay: 60
(2)延遲複製使用場景
1)確保在主庫上被錯誤修改的數據能及時找回
2)測試在從庫IO集中在恢復bin log過程中對應用程序的訪問影響
3)保留一份若干天前的數據庫狀態,和當前狀態可以做對比
2、半同步複製
(1)半同步複製
當主庫執行一個更新操作事務時,提交操作會被阻止直到至少有一個半同步的複製slave確認已經接收到本次更新操作,主庫的提交操作纔會繼續;半同步複製的slave發送確認消息只會在本次更新操作記錄已經記錄到本地的relay log之後,如果沒有任何slave發送確認消息而導致超時時,半同步複製會轉換成異步複製
(2)配置半同步複製
mysql5.7版本通過擴展的方式支持了半同步複製, 在建立半同步前需要分別在主庫和從庫安裝一個插件。
主庫的配置:
# 在主庫上安裝插件並配置主庫
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
# 開啓主庫半同步複製
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 設置主庫半同步複製超時時間,超過此時間則轉爲異步複製
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 5;
從庫的配置:
# 在備庫上安裝插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
# 在備庫開啓半同步複製
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
# 重啓備庫slave進程
mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;
3、半同步複製狀態查看
半同步複製狀態的查看可通過” SHOW STATUS LIKE 'Rpl_semi_sync%';”命令查看。
# 在主庫上查看半同步狀態
mysql> SHOW STATUS LIKE 'Rpl_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 | 9090 |
| Rpl_semi_sync_master_tx_wait_time | 9090 |
| 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 |
+--------------------------------------------+-------+
# 從庫上查看半同步狀態
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
主要參數說明:
Rpl_semi_sync_master_clients:檢查半同步的slave個數
Rpl_semi_sync_master_status:ON表示主庫的半同步功能開啓並且運行正常,OFF表示主庫的半同步功能關閉或者半同步複製 已經變成了異步複製
Rpl_semi_sync_master_no_tx:表示有多少提交沒有收到slave的確認消息
Rpl_semi_sync_master_yes_tx:表示有多少個提交收到了slave的確認消息
Rpl_semi_sync_slave_status:ON表示備庫上slave功能開啓並且運行正常,OFF表示功能爲開啓或者運行異常