mariadb複製模型主從複製、半同步複製、雙主複製、多主複製、以及啓用ssl
環境:虛擬機CentOS6.5x64 mariadb-10.0.23
mariadb編譯安裝方式和mysql類同mariadb下載地址https://downloads.mariadb.org/
原理:mysql的複製是將主服務器的二進制日誌發往從服務器,從服務器保存爲中繼日誌,然後將中繼日誌執行寫入數據庫的過程。
使用show global variables like '%log%';查看與日誌相關的全局變量
使用SET[GLOBAL | SESSION] system_var_name = expr設置全局或當前會話變量值(如果不想重啓後失效需要寫入到my.cnf的[mysqld]裏面)
二進制日誌:記錄的數據修改相關的操作,是用來實現數據恢復和複製的憑據。
log_bin = {ON|OFF},還可以是一個文件路徑
log_bin_trust_function_creators 不阻止任何存儲函數
sql_log_bin = {ON|OFF} 當前會話是否將二進制文件進入進二進制文件
sql_log_off 是否將一般查詢日誌記入查詢日誌
sync_binlog 同步緩衝中的二進制日誌到硬盤的時間,1不基於時間同步,只在事件提交時同步
binlog_format = {|statement|row|mixed} 基於語句|基於行|混合模式
max_binlog_cache_size = mysql二進制日誌的緩衝區大小,僅用於緩存事務類的語句
max_binlog_stmt_cache_size 語句緩衝區大小,即事務類和非事務類共用的大小
max_binlog_size 二進制日誌文件的上限,單位爲字節
建議:切勿將二進制日誌與數據文件放在同一設備
可以臨時通過sql_log_bin來控制二進制的寫入
中繼日誌:
對於非從服務器 中繼日誌沒有啓用
relay_log_purge = {ON|OFF} 是否自動清理不在需要的中繼日誌
relay_log_space_limit 中繼大小是否限制
授權:
grant 權限類型 ON 操作對象 to 用戶@主機 IDENTIFIED BY 密碼
備份:
mysqldump
1、完全備份 (--all-databases備份所有表)
mysqldump --databases mdb mydb --lock-all-tables --flush-logs --master-data=2 >/tmp/mariadb.sql
2、導出二進制日誌文件進行增量備份head -30 /tmp/mariadb.sql
根據查看完全備份mariadb.sql獲取下次開始的二進制日誌文件的偏移量MASTER_LOG_POS=367已經日誌文件master-bin.000004
-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000004', MASTER_LOG_POS=367;
3、現在在mdb.class裏面插入數據,並刪掉mdb數據庫,然後恢復到mdb.class插入數據的狀態
insert into mdb.class(classname) values('張三丰'),('碧瑤');
drop database mdb;
4、恢復,關閉當前會話的二進制日誌記錄,然後使用mariadb.sql恢復,然後使用二進制日誌恢復到插入數據狀態。
1)、 set session sql_log_bin=0 暫時關閉二進制日誌;show master status;記錄一下檔期的二進制偏移量
2)、 source /tmp/mariadb.sql; 並查看select * from mdb.class;這時還沒有插入的數據
3)、 mysqlbinlog --start-position=367 /mariadb/log-bin/master-bin.000004找到刪除之前的哪一點 at位置爲截至位置
# at 590
#160121 11:33:45 server id 22 end_log_pos 628 GTID 0-22-190
/*!100001 SET @@session.gtid_seq_no=190*//*!*/;
# at 628
#160121 11:33:45 server id 22 end_log_pos 712 Querythread_id=4exec_time=0error_code=0
SET TIMESTAMP=1453347225/*!*/;
drop database mdb
/*!*/;
DELIMITER ;
mysqlbinlog --start-position=367 --stop-position=628 /mariadb/log-bin/master-bin.000004 >/tmp/mariadb1.sql
4)、source /tmp/mariadb1.sql 然後查看select * from mdb.class;
MariaDB [mdb]> select * from mdb.class;
+---------+-----------+
| classid | classname |
+---------+-----------+
| 1 | 華山 |
| 2 | e mei |
| 3 | shao lin |
| 4 | xiao yao |
| 6 | 張三丰 |
| 8 | 碧瑤 |
+---------+-----------+
Lvm-snapshot:基於LVM快照的備份:前提數據目錄本身是一個lv,vg有可用空間。
創建snapshot的大小並不需要和原始卷一樣大,其大小僅僅只需要考慮兩個方面:從shapshot創建到釋放這段時間內,估計塊的改變量有多大;數據更新的頻率。一旦snapshot的空間記錄滿了原始卷塊變換的信息,那麼這個snapshot立刻被釋放,從而無法使用,從而導致這個snapshot無效。
lvcreate -L 100M -s -n mydata-snap -p r /dev/myvg/mydata
-L 指定大小
-s 指定創建快照 snapshot
-n 指定名稱 name
-p 指定類型 讀,寫
/dev/myvg/mydata 原卷對誰做快照
注意事項:
1、事務日誌跟數據文件必須在同一個捲上;
2、創建快照卷之前要,請求MySQL的全局鎖,在快照創建完成後釋放鎖;
3、在請求全局鎖完成之後,做一次日誌滾動;做二進制日誌文件及位置標記(手動進行mysql -e 'show master status' > /backups/master.info)
4、數據目錄所在的邏輯卷的卷組應該有空餘空間可以滿足短時間的數據修改
步驟:
1、請求全局鎖,並滾動日誌
mysql>FLUSH TABLES WITH READ LOCK;
mysql>FLUSH LOGS;
2、做二進制日誌文件及位置標記(手動進行)
mysql -e 'show master status' > /backups/master.info
3、創建快照卷
lvcreate -L size -s -n name -p r /path/to/some_lv
4、釋放全局鎖
mysql> UNLOCK TABLES
5、掛在快照卷並備份
mount /dev/myvg/mydata-snap /mnt
#cp -ar /mnt/* /backup/
6、備份完成之後,刪除快照卷
umount /mnt
lvremove /dev/myvg/mydata-snap
恢復:
1、先複製出數據目錄的二進制日誌文件,前提二進制日誌沒有損壞,需要定期備份
2、恢復時直接複製備份目錄下的文件到數據目錄***意保留文件的權限屬主屬組信息(直接刪除之前的數據目錄裏的數據)
3、做即時點還原和上邊的mysqldump恢復的3類同
mysqldump是一個單線程工具能完成InnnoDB熱備(熱備是使用-singe-transaction代替--lock-all-tables)、MyISAM溫備、Aria溫備 備份和恢復過程較慢
lvm-snapshot:接近於熱備的工具;因爲要先請求全局鎖,而後創建快照,並在創建快照完成後釋放全局鎖;
使用cp,tar等工具進行物理備份;
備份和恢復速度較快;
很難實現增量備份,並且請求全局鎖需要等待一段時間,在繁忙的服務器上尤其如此;
Xtrbackup:由Percona提供的開源備份工具,InnoDB熱備,增量備份;MyISAM溫備,不支持增量;(這裏不想結)
MySQL(MariaDB )SSL配置:目的是爲了進行加密複製 默認時關閉的(show global variables like '%ssl%';查看)
1、自籤根證書
創建證書目錄 這裏
mkdir /usr/local/mariadb/ssl/
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem
2、簽發服務器證書
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem > server-req.pem
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
openssl rsa -in server-key.pem -out server-key.pem
3、簽發客戶端證書
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem > client-req.pem
openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem
openssl rsa -in client-key.pem -out client-key.pem
驗證:openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
4.發送證書至客戶端,停止Mysqld修改my.cnf重啓,建立複製用戶,開啓複製線程
scp ca-cert.pem client-cert.pem client-key.pem 192.168.1.201:/usr/local/mariadb/ssl/
service mysqld stop
vim /usr/local/mariadb/my.cnf 這是我的配置文件路徑
ssl-ca=/usr/local/mariadb/ssl/ca-cert.pem
ssl-cert=/usr/local/mariadb/ssl/server-cert.pem
ssl-key=/usr/local/mariadb/ssl/server-key.pem
MariaDB [(none)]> show global variables like '%ssl%';
+---------------+----------------------------------------+
| Variable_name | Value |
+---------------+----------------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /usr/local/mariadb/ssl/ca-cert.pem |
| ssl_capath | |
| ssl_cert | /usr/local/mariadb/ssl/server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /usr/local/mariadb/ssl/server-key.pem |
+---------------+----------------------------------------+
授權重讀授權表測試連接
grant REPLICATION SLAVE,REPLICATION CLIENT on *.* to 'mysql'@'192.168.1.%' IDENTIFIED BY 'mysql' REQUIRE SSL;
flush privileges;
mysql -umysql -pmysql -h192.168.1.200 --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
連上去後\s查看
mysql Ver 15.1 Distrib 10.0.23-MariaDB, for Linux (x86_64) using readline 5.1
Connection id:7
Current database:
Current user:[email protected]
SSL:Cipher in use is DHE-RSA-AES256-GCM-SHA384
Current pager:stdout
Using outfile:''
Using delimiter:;
Server:MariaDB
Server version:10.0.23-MariaDB-log Source distribution
Protocol version:10
Connection:192.168.1.200 via TCP/IP
Server characterset:utf8
Db characterset:utf8
Client characterset:utf8
Conn. characterset:utf8
TCP port:3306
Uptime:14 min 45 sec
主從複製:
開啓從服務器的中繼日誌,更改serverID,關掉從的二進制日誌(可選)如果是級聯複製那麼該二進制日誌必須開啓。
server-id = 11 serverID
skip_slave_start 跳過重啓後自動開啓複製線程
relay_log = /mariadb/relay-log/relay-bin 中繼日誌 ssl-ca=/usr/local/mariadb/ssl/ca-cert.pem 根證書
ssl-cert=/usr/local/mariadb/ssl/client-cert.pem 證書
ssl-key=/usr/local/mariadb/ssl/client-key.pem 祕鑰
查看主服務器當前使用的日誌文件,及偏移量
MariaDB [(none)]> show master status\G
*************************** 1. row *************************** File: master-bin.000006
Position: 1128
將從服務器只想主服務器前提指向之前需要確保兩個數據庫本身數據一致,不一致的話可以將主服務器備份在從服務器上恢復。
CHANGE MASTER TO MASTER_HOST='192.168.1.200', MASTER_USER='mysql', MASTER_PASSWORD='mysql', MASTER_LOG_FILE='master-bin.000006', MASTER_LOG_POS=1128, MASTER_SSL=1, MASTER_SSL_CA = '/usr/local/mariadb/ssl/ca-cert.pem', MASTER_SSL_CERT = '/usr/local/mariadb/ssl/client-cert.pem', MASTER_SSL_KEY = '/usr/local/mariadb/ssl/client-key.pem';
然後開啓複製線程並查看狀態,START SLAVE [IO_THREAD|SQL_THREAD] IO_THREAD讀取主服務器二進制文件寫入從中繼日誌SQL_THREAD讀取中繼日誌並執行
start slave;
show slave status\G
驗證在主服務器創建一個數據庫看看從服務器有沒有。基本上結束
半同步複製:主服務器完成一個事物時需要等待從服務器中的某一個完成了該事物後才返回結果,注:只需要等待其中一個,所以稱爲半同步
安裝插件啓用參數
ls /usr/local/mariadb/lib/plugin/ semisync_master.so
主
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
show global variables like '%semi%';
rpl_semi_sync_master_wait_no_slave :是否允許master 每個事物提交後都要等待slave的receipt信號。默認爲on ,每一個事務都會等待,如果slave當掉後,當slave追趕上master的日誌時,可以自動的切換爲半同步方式,如果爲off,則slave追趕上後,也不會採用半同步的方式複製了,需要手工配置。
set global rpl_semi_sync_master_enabled=1;開啓半同步複製
set global rpl_semi_sync_master_timeout=1000;設置超時時間如果第一次超時下一次直接跳過從服務器
rpl_semi_sync_master_trace_level 監控等級:
從
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';安裝插件從
show global variables like '%semi%';
set global rpl_semi_sync_slave_enabled=1;開啓從服務半同步複製
stop slave io_thread; 關閉Io線程
start slave io_thread; 啓動io線程
在主服務器
show global status like '%semi%';
MariaDB [(none)]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 | #記錄支持半同步的slave的個數
| Rpl_semi_sync_master_net_avg_wait_time | 0 | #master 等待slave回覆的平均等待時間,單位微秒
| Rpl_semi_sync_master_net_wait_time | 0 | #master 總的等待時間
| Rpl_semi_sync_master_net_waits | 0 | #master 等待slave回覆的的總的等待次數
| Rpl_semi_sync_master_no_times | 0 | #master 關閉半同步複製的次數
| Rpl_semi_sync_master_no_tx | 0 | #master 沒有收到slave的回覆而提交的次數
| Rpl_semi_sync_master_status | ON | #標記master現在是否是半同步複製狀態
| Rpl_semi_sync_master_timefunc_failures | 0 | #時間函數未正常工作的次數
| Rpl_semi_sync_master_tx_avg_wait_time | 0 | #開啓Semi-sync,事務返回需要等待的平均時間
| Rpl_semi_sync_master_tx_wait_time | 0 | #事務等待備庫響應的總時間
| Rpl_semi_sync_master_tx_waits | 0 | #事務等待備庫響應的總次數
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 | #改變當前等待最小二進制日誌的次數
| Rpl_semi_sync_master_wait_sessions | 0 | #當前有多少個session 因爲slave 的回覆而造成等待
| Rpl_semi_sync_master_yes_tx | 0 | #master 成功接收到slave的回覆的次數
+--------------------------------------------+-------+
雙主模式;
原理就是兩臺互爲主從,很顯然需要都開啓中繼日誌和二進制日誌,並且需要注意的是mariadb中的一個服務器函數auto-increment需要調整,以及要有一個具有複製權限的賬號,然後修改配置文件互指對方爲主就可以
授權參照SSL裏的授權
# 主服務器A上
[mysqld]
server-id = 10
log-bin = mysql-bin
relay-log = relay-mysql
auto-increment-offset = 1
auto-increment-increment = 2
skip_slave_start 開啓服務時不自動開啓slave複製線程
# 主服務器B上
[mysqld]
server-id = 20
log-bin = mysql-bin
relay-log = relay-mysql
auto-increment-increment = 2 # 步長
auto-increment-offset = 2 # 起始值
重啓後互指 需要提前查看對方服務器的二進制日誌文件和偏移量show master status\G 參照主從裏面的change master to如果沒有配置ssl去掉ssl選項即可。
主從的問題:當兩個用戶在對同一個表修改時,這時就會出現數據的不一致性。
多源模式:常用來收集數據 如果多個主中有數據庫名相同的就會出現數據不一致
和主從類似只需要從服務同時制定多個主服務器,只是使用的命令有一些變化,其它一致
CHANGE MASTER ['connection_name'] TO MASTER_HOST = 'host_name',MASTER_USER = 'user_name',MASTER_PASSWORD = 'password',MASTER_LOG_FILE = 'master_log_name',MASTER_LOG_POS = master_log_pos
SHOW SLAVE ['connection_name'] STATUS
SHOW ALL SLAVES STATUS
START SLAVE ['connection_name'...]]
START ALL SLAVES ...
STOP SLAVE ['connection_name'] ...
STOP ALL SLAVES ...
2個安全變量
sync_binlog=1 or N 將二進制日誌內容同步到磁盤0表示有服務器自己判斷性能最好,1表示每次有事務提交都會同步到磁盤(性能最差最安全),N表示N次事務後同步
innodb_flush_log_at_trx_commit = 1
innodb_flush_log_at_trx_commit = 0,Innodb 中的Log Thread 沒隔1 秒鐘會將log buffer中的數據寫入到文件,同時還會通知文件系統進行文件同步的flush 操作,保證數據確實已經寫入到磁盤上面的物理文件。但是,每次事務的結束(commit 或者是rollback)並不會觸發Log Thread 將log buffer 中的數據寫入文件。所以,當設置爲0 的時候,當MySQL Crash 和OS Crash 或者主機斷電之後,最極端的情況是丟失1 秒時間的數據變更。
innodb_flush_log_at_trx_commit = 1,這也是Innodb 的默認設置。我們每次事務的結束都會觸發Log Thread 將log buffer 中的數據寫入文件並通知文件系統同步文件。這個設置是最安全的設置,能夠保證不論是MySQL Crash 還是OS Crash 或者是主機斷電都不會丟失任何已經提交的數據。
innodb_flush_log_at_trx_commit = 2,當我們設置爲2 的時候,Log Thread 會在我們每次事務結束的時候將數據寫入事務日誌,但是這裏的寫入僅僅是調用了文件系統的文件寫入操作。而我們的文件系統都是有緩存機制的,所以Log Thread 的這個寫入並不能保證內容真的已經寫入到物理磁盤上面完成持久化的動作。文件系統什麼時候會將緩存中的這個數據同步到物理磁盤文件Log Thread 就完全不知道了。所以,當設置爲2 的時候,MySQL Crash 並不會造成數據的丟失,但是OS Crash 或者是主機斷電後可能丟失的數據量就完全控制在文件系統上了。各種文件系統對於自己緩存的刷新機制各不一樣,大家可以自行參閱相關的手冊。