目錄
1. 主從MySQL主從複製介紹
MySQL的主從複製方案,其實就和文件及文件系統級別同步是類似的,都是數據的傳輸,只不過MySQL無需藉助第三方工具,而是自帶的同步複製功能,另外一點,MySQL的主從複製並不是磁盤上文件直接同步,而是邏輯的binlog日誌同步到本地在應用執行的過程。
MySQL數據庫支持單向、雙向、鏈式級聯等不同場景的複製,在複製過程中,一臺服務器充當主服務器(Master),而一個或多個其它的服務器充當從服務器(Slave)。
複製可以單向:M==>S;可以雙向:M<==>S;當然也可以多M環裝同步等。
如果設置了鏈式級聯複製,那麼,從(slave)服務器本身除了充當從服務器外,也會同時充當其下面從服務器的主服務器,鏈式級聯複製類似A==>B==>C==>D的複製形式。
下面是MySQL各種同步結構的邏輯圖:
1. 單向主從複製邏輯圖,此架構只能在Master端進行數據寫入
2. 雙向主主同步邏輯圖,此架構可以在Master1端或Master2端進行數據寫入
3. 線性級聯單向雙主同步邏輯圖,此架構只能在Master端進行數據寫入
4. 環裝級聯單向多主同步邏輯圖,任意一個點都可以寫入數據
5. 環裝級聯單向多主多從同步邏輯圖,次架構只能在任意一個master端進行數據寫入
6. MySQL官方同步架構圖
在當前的生產環境中,MySQL主從複製都是異步的複製方式,既不是嚴格實時的數據同步。
2. MySQL主從複製的企業應用場景
MySQL主從複製集羣功能使得MySQL數據庫支持大規模高併發讀寫稱爲可能,同時有效的保護了物理服務器宕機場景的數據備份。
應用場景1:從服務器作爲主服務器的實時數據備份
主從服務器架構的設置可以大大加強MySQL數據庫架構的健壯性,例如:當主服務器出現問題時,我們可以人工或設置自動切換到從服務器繼續提供服務,此時從服務器的數據與宕機時的數據庫幾乎是一致的。
這類似NFS存儲數據通過inotify+rsync同步到備份的NFS服務器,只不過MySQL的複製方案是其自帶的工具。
利用MySQL的複製功能進行數據備份時,在硬件故障、軟件故障的場景下,該數據備份是有效的,但對於人爲執行drop、delete等語句刪除數據的情況,從庫的備份功能就沒用了,因爲從服務器也會執行刪除的語句。
應用場景2:主從服務器實現讀寫分離,從服務器實現負載均衡
主從服務器架構可通過(PHP、java等)或代理軟件(mysql-proxy、Amoeba)實現對用戶(客戶端)的請求讀寫分離,揖讓從服務器金聰處理用戶的select查詢請求,降低用戶查詢響應時間,以及同時讀寫在主服務器上帶來的訪問壓力,對於更新的數據(例如:update、insert、delete語句),則仍然交給主服務器處理,確保主服務器和從服務器保持實時同步。
應用場景3:把多個從服務器根據業務重要性進行拆分訪問
可以把幾個不同的從服務器,根號月公司的業務進行拆分,例如:在爲外部用戶提供查詢服務的從服務器,在內部DBA用來數據備份的從服務器,還有爲公司內部人員提供訪問的後臺、腳本、日誌分析及供開發人員查詢使用的從服務器,這樣拆分除了減輕主服務器的壓力外,還可以是數據庫對外不用戶瀏覽,內部用戶業務處理及DBA人員的備份等互不影響。
3. 實現MySQL主從讀寫分離的方案
(1)通過程序實現讀寫分離(性能和效率最佳,推薦)
PHP和java程序都可以通過設置多個連接文件輕鬆地實現對數據庫的讀寫分離,即當語句關鍵字爲select時,就去連接讀庫的連接文件,若爲update、insert、delete時,則連接寫庫的文件。
通過程序實現讀寫分離的缺點就是需要開發人員對程序進行改造,使其對下層不透明,但這種方式更容易開發和實現,適合互聯網業務場景。
(2)通過開源的軟件實現讀寫分離
MySQL-Proxy、Amoeba等代理軟件也可以是實現讀寫分離功能,這些軟件的穩定性和功能一般,不建議生產使用,絕大多數公司常用的還是在應用端發程序實現讀寫分離。
(3)大型門戶獨立開發DAL層綜合軟件
百度、阿里等大型門戶都有開發牛人,會花大力氣開發適合自己業務的讀寫分離,負載均衡,監控報警,自動擴容,自動收縮等一系列功能的DAL層軟件。
4. MySQL主從複製原理
簡單描述MySQL Replication的複製原理過程
1. 在Slave服務器上執行start slave命令開啓主從複製開關,開始進行主從複製。
2. 此時,slave服務器的I/O線程會通過在Master上已經授權的複製用戶權限請求選擇Master服務器,並 請求從指定binlog日誌文件的指定位置(日誌文件名和位置就是在哦誒之主從瀆職服務時執行change master命令指定的)之後,之後開始發送binlog日誌內容。
3. Master服務器接收來自slave服務器的IO線程的請求後,其上負責複製的I/O線程會根據slave服務器 的io線程請求的信息分批讀取指定binlog日誌文件指定位置之後的binlog日誌信息,然後返回給 slave端的I/O線程,返回的信息中除了binlog日誌內容外,還有在master服務器端記錄的新的binlog 文件名稱,以及在新的binlog中的下一個指定的跟新位置。
4. 當slave服務器的io線程獲取帶master服務器上io線程發送的日誌內容,日誌文件及位置點後,會將 binlog日誌內容寫到slave端自身的relay loy(即中繼日誌)的最末端,並將新的binlog日誌文件名 和位置點記錄到master-info文件中,以便下一次讀取master端新的binlog日誌是能夠告訴master服 務端從新的binlog日誌指定文件及位置開始請求新的binlog日誌內容。
5.slave服務器端的SQL線程會實時監測本地relay log中的io線程新增加的日誌內容。然後及時的把 relay.log文件中的內容解析成SQL語句,並且自身slave服務器上按解析sql語句的位置順序執行應用 這些SQL語句,並在relay-log.info中記錄當前應用中繼日誌文件名及位置點。
MySQL主從複製原理的重點小結:
主從複製是異步的邏輯的SQL語句級的複製
複製時,主庫有一個線程,從庫有兩個線程,即I/O和SQL線程
實現主從複製的前提條件時主庫開啓記錄binlog功能
作爲複製的所有MySQL節點的sever id都不能相同
binlog文件只記錄對數據有更改的SQL語句(來自主數據庫內容的變更),不記錄任何查詢(如:select、show)語句。
5. 主從複製實戰
實現主從複製條件
開啓binlog功能。
主庫建立同步賬號。
從庫配置master.info(change master..)。
startslave複製開關。
5.1 主從配置
如圖:
配置主從複製
測試環境:使用一臺服務器,多實例,一個實例做主,另外的實例做從(多臺服務器也一樣)
(1)主庫操作
1. 先確認主庫binlog功能是否開啓和各個實例server-id實例的不同
[root@db01 3308]# egrep "log-bin|server-id" /data/{3306,3307}/my.cnf /data/3306/my.cnf:log-bin= /data/3306/mysql-bin /data/3306/my.cnf:server-id= 1 /data/3307/my.cnf:#log-bin= /data/3307/mysql-bin /data/3307/my.cnf:server-id= 3
2. 主庫授權同步的用戶
[root@db01 /]# mysql -uroot -poldboy123 -S /data/3306/mysql.sock #<== 登錄數據庫 mysql> grant replication slave on *.* torep@'172.16.1.%' identified by 'oldboy123'; Query OK, 0 rowsaffected (0.00 sec) #<== 創建rep用戶並授權 mysql> flush privileges; #<== 刷新數據庫 Query OK, 0 rowsaffected (0.00 sec) mysql> select user,host from mysql.user; #<== 創建用戶後查看確認 mysql> show grants for rep@'172.16.1.%'; #<== 查看rep用戶權限
3. 備份前對主數據庫鎖表(只讀)
mysql> flush table with read lock; Query OK, 0 rowsaffected (0.00 sec)
測試:單開一個窗口,創建一個數據庫(這時會發現創建不了,因爲表鎖了)
mysql> create database oldgirl;
4. 查看全備與增量之間的臨界點
mysql> show master status; +-----------------+------------+---------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-----------------+------------+---------------+------------------+ | mysql-bin.000016| 4065 | | | +-----------------+------------+---------------+------------------+ 1 row in set (0.00sec)
5. 開始備份
創建備份目錄
[root@db01 ~]# mkdir -p /server/backup/
全備
[root@db01~]# mysqldump -uroot -poldboy123 -S/data/3306/mysql.sock -B -A --events|gzip >/server/backup/rep_bak_$(date+%F).sql.gz [root@db01 ~]# ll -htr /server/backup/|tail -1 -rw-r--r-- 1 root root 149K Aug 31 23:57rep_bak_2016-08-31.sql.gz
6. 因爲數據已經備份完,所以可以開放用戶寫入功能,此時會發現測試窗口的數據會寫入
mysql> unlock tables; Query OK, 0 rows affected (0.00 sec)
(2)從庫操作
1. 確保所有用戶server-id不同(主庫已經確認過)
[root@db01 3308]# egrep "log-bin|server-id" /data/{3306,3307}/my.cnf /data/3306/my.cnf:log-bin= /data/3306/mysql-bin /data/3306/my.cnf:server-id= 1 /data/3307/my.cnf:#log-bin= /data/3307/mysql-bin /data/3307/my.cnf:server-id= 3
2. 把主庫的全備導入到從庫
[root@db01 ~]# gzip -d/server/backup/rep_bak_2016-08-31.sql.gz [root@db01 ~]# ll /server/backup/rep_bak_2016-08-31.sql -rw-r--r-- 1 root root 552788 Aug 31 23:57//server/backup/rep_bak_2016-08-31.sql [root@db01 ~]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock </server/backup/rep_bak_2016-08-31.sql
3. 找位置點,開始配置masterinfo
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock CHANGE MASTER TO MASTER_HOST='172.16.1.51', #<== 主庫IP MASTER_PORT=3306, #<== 主庫端口(如果配置一主多從可不寫,默認) MASTER_USER='rep', #<== 這裏是主庫上建立的用於複製的用戶rep MASTER_PASSWORD='oldboy123', #<== rep用戶密碼 MASTER_LOG_FILE='mysql-bin.000016', #<== 這裏是showmaster status; 時看到的臨界點binlog文件,注意,這裏不能多空格 MASTER_LOG_POS=107; #<== 這是showmaster status; 查看二進制文件偏移量,注意,不能多空格 [root@db01 ~]# ll /data/3307/ -rw-rw---- 1 mysql mysql 51 Sep 1 03:40 relay-log.info
參數如下:
CHANGE MASTER TO MASTER_HOST='172.16.1.51', MASTER_PORT=3306, MASTER_USER='rep', MASTER_PASSWORD='oldboy123', MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=107;
4. 開啓同步開關
mysql> start slave; Query OK, 0 rowsaffected (0.01 sec)
5. 查看同步狀態,看到以下黃色部分是以下狀態就算成功
mysql> show slave status\G *************************** 1. row*************************** -----------------------省略部分內容------------ Relay_Master_Log_File: mysql-bin.000017 Slave_IO_Running: Yes #<== 看這IO線程yes和SQLyes就成功了 Slave_SQL_Running: Yes Replicate_Do_DB: -------------------------------------省略----------- Seconds_Behind_Master: 0 #<== 主到從複製的延遲 1 row in set (0.00 sec)
或者使用命令查看:
mysql -S /data/3307/mysql.sock -e"show slave status\G"|egrep -i "_running|Behind " Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0
(3)簡單測試是否成功
1. 在主庫創建數據庫,查看從庫是否同步
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3306/mysql.sock mysql> show databases; +-----------------------+ | Database | +-----------------------+ | information_schema | | mysql | | performance_schema | +-----------------------+ 8 rows in set (0.00 sec)
mysql> create database testdatabase; Query OK, 1 row affected (0.00 sec) mysql> show databases; +-----------------------+ | Database | +-----------------------+ | information_schema | | mysql | | performance_schema | | testdatabase | +-----------------------+ 9 rows in set (0.00 sec)
登錄從庫查看
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock mysql> show databases; +-------------------------------+ | Database | +-------------------------------+ | information_schema | | mysql | | performance_schema | | testdatabase | +-------------------------------+ 9 rows in set (0.00 sec)
------------------成功!!!-------------------
5.2 MySQL數據庫級聯配置
說明:在配置了MySQL一主一從或MySQL一主多從的情況下,在該基礎上的從庫下面在配置一臺從庫,構成線性級聯單向雙主同步。
環境:在以上5.1的配置上繼續配置級聯
以下在以上配置的3307從庫上操作
1. 開啓從庫3309記錄binlog日誌功能,配置如下:
[root@db01 3307]# vim /data/3307/my.cnf [mysqld] log-slave-updates #<==在從庫上配置binloa文件時,此行也是必須加的 log-bin = /data/3309/mysql-bin
重啓生效
[root@db01 3307]# /data/3307/mysql restart Restarting MySQL... Stoping MySQL... Starting MySQL..
2. 全備3307從庫實例,導入到3309
[root@db01 3307]# mysqldump -uroot -poldboy123 -S/data/3307/mysql.sock -B -A --master-data=1 --events>/server/backup/3307.sql [root@db01 3307]# mysql -uroot-poldboy123 -S /data/3309/mysql.sock </server/backup/3307.sql
以下步驟在3309上面操作
3. 在3309上面配置master info文件
[root@db01 3309]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock mysql> CHANGE MASTER TO ->MASTER_HOST='172.16.1.51', ->MASTER_PORT=3307, ->MASTER_USER='rep', ->MASTER_PASSWORD='oldboy123'; Query OK, 0 rows affected (0.01 sec) 說明:這裏沒有進行查看並指定binlog文件的位置點是因爲備份時已經使用參數-x(鎖表),和--master-data=1 (標記binlog文件數據位置)兩個參數,--master-data=1會自動會自動生成位置點。
參數如下:
CHANGEMASTER TO MASTER_HOST='172.16.1.51', MASTER_PORT=3307, MASTER_USER='rep', MASTER_PASSWORD='oldboy123';
4. 在3309上面開啓slave開關
mysql> start slave; Query OK, 0 rows affected (0.00 sec)
5. 查看狀態
mysql> show slave status\G Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 說明:以上輸出部分內容省略,只要以上三行是該狀態就表示正確(此三行是配置成功標誌最關鍵的參數)
# 還可以在命令行外執行命令查看,如下:
[root@db01 3309]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock -e "showslave status\G"|egrep -i "_running|Seconds" Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0
測試:
在主庫3306裏面寫入數據,這時在3307庫裏面和3309庫裏面就會同時有啦,如下:
# 在3306查看並創建數據庫
[root@db01 3308]# mysql -uroot -poldboy123 -S/data/3306/mysql.sock mysql> show databases; +---------------------+ | Database | +---------------------+ | information_schema | | mysql | | oldboy | | performance_schema | +---------------------+ 4 rows in set (0.00 sec)
mysql> create database zyl; #<== 創建名爲zyl的庫
mysql> show databases; #<==在3306上面查看 +-------------------------------+ | Database | +-------------------------------+ | information_schema | | mysql | | oldboy | | performance_schema | | zyl | +-------------------------------+ 5 rows in set (0.00 sec)[
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock mysql> show databases; #<==在3307上面查看 +-------------------------------+ | Database | +-------------------------------+ | information_schema | | mysql | | oldboy | | performance_schema | | zyl | +-------------------------------+ 5 rows in set (0.00 sec)
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock mysql> show databases; #<==在3309上面查看 +---------------------+ | Database | +---------------------+ | information_schema | | mysql | | oldboy | | performance_schema | | zyl | +---------------------+ 5 rows in set (0.00 sec)
報錯原因: 1. 防火牆原因;
2. 複製賬號和密碼不對。
5.3 MySQL主從複製配置步驟小結
1. 一主一從環境爲一臺服務器(多實例),3306爲主,3307爲從,3309爲級聯。
2. 配置my.cnf文件,主庫配置bin-log和server-id出本書,從庫配置sever-id,該值個庫不能一樣,一般不開啓從庫的binlog功能,但是在5.2因爲在3307從庫下還有配置級聯從庫,所以需要開啓。配置這些參數要重啓才能生效。
3. 登錄主庫,增加從庫連接主庫同步的賬戶,例如:rep、並授權replication slave複製同步的權限。
4. 登錄主庫,整庫鎖表flus tablewith read lock(窗口關閉後即失效,超時參數設定的時間到了,鎖表也會失效),然後show master status查看binlog的位置狀態。
5 . 離開窗口,在linux命令行備份導出原有的數據庫數據,並拷貝到從庫所在的服務器目錄,如果數據量龐大,並且允許停機,可以停機打包,而不用mysqldump。
6. 導出主庫數據後,執行unlocktables解鎖主庫。
7. 把主庫導出的數據恢復到從庫。
8. 根據主庫的show masterstatus查看到的binlog的位置狀態,在從庫執行change master to...語句。
9. 從庫開啓複製開關,即執行Lstartslave;。
5.4 主從配置表示成功後的關鍵參數說明
主從複製是否配置成功,最關鍵的是下面的3項狀態參數
Slave_IO_Running:Yes:
這個是I/O線程狀態,I/O線程複製從主庫到從庫讀取binlog日誌,並寫入從庫的中繼日誌,狀態爲yes表示I/O線程工作正常。
Slave_SQL_Running:Yes:
這個是SQL線程狀態,SQL線程負責讀取中繼日誌(relay-log)中的數據並裝換爲SQL語句應用到數據庫中,狀態爲YES表示I/O線程工作正常。
Seconds_Behind_Master:0:
這個是複製過程中從庫比主庫延遲的描述,這個參數很重要,但企業更準確地判斷主從延遲的方法爲:在主庫寫時間戳,然後從庫讀取時間戳,和當前數據庫時間進行比較,從而認定是否延遲。
5.5 MySQL主從複製配置問題彙總
1. 主庫show master status沒返回狀態結果,如下:
mysql> show master status; 0 row in set (0.00 sec)
原因:binlog功能開關沒開或沒生效導致。正確開啓方式如下:
[root@db01 3307]# grep "log-bin"/data/3306/my.cnf log-bin = /data/3306/mysql-bin #<== 在配置文件中將此行註釋打開 [root@db01 3307]# mysql -uroot -poldboy123 -S /data/3306/mysql.sock-e "show variables like 'log_bin';" #<== 修改後查看結果 +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | ON | +---------------+-------+
2. 出現錯誤信息:“Last_IO_Error:GOTdatal errow 1236 drom master when when reading data from binary log; ‘ Couldnot find first log file name in binary log index file’ ”
原因:以上故障原因是執行CHANGE MASTER 命令時,某一個參數的值多個空格導致,如下:
CHANGE MASTER TO MASTER_HOST='172.16.1.51', MASTER_PORT=3307, MASTER_USER='rep', MASTER_PASSWORD='oldboy123'; 說明;以上參數均不能有空格
3. MySQL服務無法啓動
[root@db01 /]# /data/3306/mysql start MySQL is running... #<==正在運行 [root@db01 /]# ps -ef|grep mysql #<== 並無mysql進程 root 30345 26941 0 22:16 pts/4 00:00:00 grep mysql
原因:其原因是啓動腳本里對mysql.sock是否存在做了判斷,如果存在mysql.sock,就認爲服務運行,這是個bug,解決如下:
[root@db01 /]# rm -f /data/3306/mysql.sock # 說明:刪除後重新啓動查看即可
4. 當從起或關閉MySQL服務從起或關閉不了,報錯如下:
[root@db01 3307]# /data/3307/mysql restart Restarting MySQL... Stoping MySQL... /application/mysql/bin/mysqladmin: connect toserver at 'localhost' failed error: 'Access denied for user 'root'@'localhost'(using password: YES)' MySQL is running...
原因:是啓動文件/data/3306/mysql裏面沒有修改數據庫密碼,當我們設置完密碼後,在mysql啓動文件mysql中也是有密碼的,如果不改,就無法停止服務。
[root@db01 /]# vim /data/3306/mysql mysql_pwd="oldboy123"
6. MySQL主從複製更多應用技巧
1.工作中MySQL從庫停止複製故障案例
模擬重現故障的能力是運維人員最重要的能力。下面就來次模擬操作。先在從庫創建一個庫,然後去主庫創建同名的庫來模擬數據衝突,命令如下:
show slave status;報錯:且 show slavestatus\G: Slave_IO_Running:Yes Slave_SQL_Running:NO Seconds_Behind_Master:NULL Last_Error:Error 'Can't create database 'xiaoliu';database exists' onquery. Default database:'xiaoliu'. Query:'create database xiaoliu'
對於該衝突,解決方法1如下:
top slave; #<== 臨時停止同步開關 set global sql_slave_skip_counter =1; #<== 將同步指針向下移動一個,如果多次不同步,可以重複操作 start slave; #<== 沖洗你開啓 show slave status\G: #<== 再次進行查看確認
如果修改後還會報錯,那可以適當的將set global sql_slave_skip_counter值增大即可。
提示:setglobal sql_slave_skip_counter=n;#n取值>0,忽略執行N個更新。
解決方法2:根據可以忽略的錯誤號事先在配置文件中配置,跳過指定的不影響業務數據的錯誤,例如:
root@MySQL ~]# grep slave-skip /data/3306/my.cnf slave-skip-errors = 1032,1062,1007
提示:類似由於入庫重複導致的失敗可以忽略,其他情況是不是可以忽略需要根據不同公司的具體業務來評估。可以查看博客的代碼含義
其他可能引起復制故障的原因:
MySQL自身的原因及人爲重複插入數據。
不同的數據庫版本會引起不同步,低版本到高版本可以,但是高版本不能往低版本同步。
·MySQL的運行錯誤或程序bug。
·binlog記錄模式,例如:row level模式就比默認的語句模式要好。
2. 讓MySQL從庫記錄binlog日誌的方法
從庫需要記錄binlog的應用場景:當前的從庫還要作爲其他從庫的主庫,例如級聯複製或雙主互爲主從場景的情況下。下面介紹從庫記錄binlog日誌的方法。
在從庫的my.cnf中加入如下參數,然後重啓服務生效即可。
log-slave-updates #<== 必須要有這個參數 log-bin = /data/3307/mysql-bin #<==開啓從庫binlog功能 expire_logs_days = 7 #<==相當於find/data/3307/ -type f -name " mysql-bin.000*" -mtime +7 |xargs rm -f
3. MySQL主從複製集羣架構的數據備份策略
有主從複製了,還需要做定時全量加增量備份麼?答案是肯定的!
因爲,如果主庫有語句級誤操作(例如:drop database oldboy;),從庫也會執行drop databaseoldboy;,這樣MySQL主從庫就都刪除了該數據。
把從庫作爲數據庫備份服務器時,備份策略如下:
高併發業務場景備份時,可以選擇在一臺從庫上備份(Slave5),把從庫作爲數據庫備份服務器時需要在從庫開啓binlog功能,其邏輯如圖所示。
步驟如下:
1.選擇一個不對外提供服務的從庫,這樣可以確保和主庫更新最接近,專門用於做數據備份。
2.開啓從庫的binlog功能。
備份時可以選擇只停止SQL線程,停止應用SQL語句到數據庫,I/O線程保留工作狀態,執行命令爲stop slave sql_thread;,備份方式可以採取mysqldump邏輯備份或直接物理備份,例如:使用cp、tar(針對/data/目錄)工具或xtrabackup(第三方的物理備份軟件)進行備份,則邏輯備份和物理備份的選擇,一般是根據總的備份數據量的多少進行選擇的,數據量低於30G,建議選擇mysqldump邏輯備份方法,安全穩定,最後把全備和binlog數據發送到備份服務器上留存。
4. MySQL主從複製延遲問題的原因及解決方案
問題一:主庫的從庫太多,導致複製延遲。
從庫數量以3~5個爲宜,要複製的從節點數量過多,會導致複製延遲。
問題二:從庫硬件比主庫差,導致複製延遲。
查看Master和Slave的系統配置,可能會因爲機器配置不當,包括磁盤I/O、CPU、內存等各方面因素造成複製的延遲。這一般發生在高併發大數據量寫入場景U、內存等各方面因素造成複製的延遲。這一般發生在高併發大數據量寫入場景中。
問題三:慢SQL語句過多。
假如一條SQL語句執行時間是20秒,那麼從執行完畢到從庫上能查到數據至少需要20秒,這樣就延遲20秒了。
一般要把SQL語句的優化作爲常規工作,不斷地進行監控和優化,如果單個SQL的寫入時間長,可以修改後分多次寫入。通過查看慢查詢日誌或show fullprocesslist命令,找出執行時間長的查詢語句或大的事務。
問題四:主從複製的設計問題。
例如,主從複製單線程,如果主庫寫併發太大,來不及傳送到從庫,就會導致延遲。
更高版本的MySQL可以支持多線程複製,門戶網站則會自己開發多線程同步功能。
問題五:主從庫之間的網絡延遲。
主從庫的網卡、網線、連接的交換機等網絡設備都可能成爲複製的瓶頸,導致複製延遲,另外,跨公網主從複製很容易導致主從複製延遲。
問題六:主庫讀寫壓力大,導致複製延遲。
主庫硬件要搞好一點,架構的前端要加buffer及緩存層。
5. 通過read-only參數讓從庫只讀訪問
read-only參數選項可以讓從服務器只允許來自從服務器線程或具有SUPER權限的數據庫用戶進行更新,確保從服務器不接受來自用戶端的非法用戶更新。
read-only參數允許數據庫更新的條件爲:
具有SUPER權限的用戶可以更新,不受read-only參數影響,例如:管理員root。
來自從服務器線程可以更新,不受read-only參數影響,例如:前文的rep用戶。
在生產環境中,可以在從庫Slave中使用read-only參數,確保從庫數據不被非法更新。
read-only參數的配置方法如下。
方法一:直接帶--read-only參數啓動或重啓數據庫,使用
killall mysqld
或
mysqladmin -uroot -poldboy123 -S/data/3307/mysql.sock shutdown mysqld_safe --defaults-file=/data/3307/my.cnf--read-only &
方法二:在my.cnf裏[mysqld]模塊下加read-only參數重啓數據庫,配置如下:
[mysqld] read-only
6.Web用戶專業設置方案:MySQL主從複製讀寫分離集羣
專業的運維人員提供給開發人員讀寫分離的賬戶設置方法如下:
1)訪問主庫和從庫時使用一套用戶密碼,例如,用戶爲web,密碼爲oldboy123。
2)即使訪問IP不同,端口也儘量相同(3306)。例如:寫庫VIP爲10.0.0.7,讀庫VIP爲10.0.0.8。
除了IP沒辦法修改之外,要儘量爲開發人員提供方便,如果數據庫前端有DAL層(DBProxy),還可以只給開發人員一套用戶、密碼、IP、端口,這樣就更專業了,剩下的都由運維人員搞定。
下面是授權Web連接用戶訪問的方案:MySQL主從複製讀寫分離集羣。
方法1:主庫和從庫使用不同的用戶,授予不同的權限。
主庫上對web_w用戶授權如下:
用戶:web_w 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.7
權限:SELECT,INSERT,UPDATE,DELETE
命令: GRANT SELECT,INSERT,UPDATE,DELETE ON `web`.* TO 'web_w'@'10.0.0.%' identified by 'oldboy123';
從庫上對web_r用戶授權如下:
用戶:web_r 密碼:oldboy123 端口:3306 從庫VIP:10.0.0.8
權限:SELECT
命令: GRANT SELECT ON `web`.* TO 'web_r'@'10.0.0.%' identified by'oldboy123'
提示:此法顯得不夠專業,但是可以滿足開發需求。
方法2:主庫和從庫使用相同的用戶,但授予不同的權限。
主庫上對web用戶授權如下
用戶:web 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.7
權限:SELECT,INSERT,UPDATE,DELETE
命令: GRANT SELECT,INSERT,UPDATE,DELETE ON `web`.* TO 'web'@'10.0.0.%'identified by 'oldboy123' ;
從庫上對web用戶授權如下:
用戶:web 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.8
權限:SELECT
提示:由於主庫和從庫是同步複製的,所以從庫上的web用戶會自動和主庫保持一致,即無法實現只讀select的授權
要實現方法2中的授權方案,有如下兩個方法。
一是在主庫上創建用戶和權限後,從庫上revoke收回對應更新權限(insert、update、delete)。
命令爲: REVOKE INSERT,UPDATE,DELETE ONweb.* FROM 'web'@'10.0.0.%';
二是忽略授權庫MySQL同步,主庫的配置參數如下:
binlog-ignore-db = mysql replicate-ignore-db = mysql
提示:上面參數等號兩邊必須有空格。
方法3:在從庫上設置read-only參數,讓從庫只讀。
主庫從庫:主庫和從庫使用相同的用戶,授予相同的權限(非ALL權限)。
用戶:web 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.7,從庫VIP:10.0.0.8
權限:SELECT,INSERT,UPDATE,DELETE
命令: GRANT SELECT,INSERT,UPDATE,DELETE ON web.* TO 'web_w'@'10.0.0.%' identified by 'oldboy123';
由於從庫設置了read-only,非super權限是無法寫入的,因此,通過read-only參數就可以很好地控制用戶,使其不能非法將數據寫入從庫
老男孩生產工作場景的設置方案如下:
1)忽略授權庫MySQL同步,主庫配置參數如下:
binlog-ignore-db = mysql replicate-ignore-db = mysql
提示:上面參數等號兩邊必須有空格。
2)主庫和從庫使用相同的用戶,但授予不同的權限。
主庫上對web用戶授權如下:
用戶:web 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.7
權限:SELECT,INSERT,UPDATE,DELETE
命令: GRANT SELECT,INSERT,UPDATE,DELETE ON web.* TO 'web'@'10.0.0.%' identified by 'oldboy123';
從庫上對web用戶授權如下:
用戶:web 密碼:oldboy123 端口:3306 主庫VIP:10.0.0.8
權限:SELECT
3)從庫設置read-only,增加雙保險。