1. MySQL 主從複製概述php
1.1 MySQL 主從複製簡介mysql
MySQL 數據庫的主從複製方案,與使用 scp/rsync 等命令進行的文件級別複製相似,都是數據的遠程傳輸,只不過 MySQL 的主從複製是其自帶的功能,無需藉助第三方工具,並且,MySQL 的主從複製並非數據庫磁盤上的文件直接拷貝,而是經過邏輯的 binlog 日誌複製到要同步的服務器本地,而後由本地的線程讀取日誌裏面的 SQL 語句,從新應用到 MySQL 數據庫中。web
1.2 MySQL 主從複製架構邏輯圖概述sql
MySQL 數據庫支持單向、雙向、鏈式級聯、環狀等不一樣業務場景的複製。在複製過程當中,一臺服務器充當主服務器(Master),接收來自用戶的內容更新,而一個或多個其餘的服務器充當從服務器(Slave),接收來自主服務器 binlog 文件的日誌內容,解析出 SQL,從新更新到從服務器,使得主從服務器數據達到一致。數據庫
若是設置了鏈式級聯複製,那麼從服務器自己除了充當從服務器外,也會同時充當其下面從服務器的主服務器,鏈式級聯複製相似 A→B→C 的複製形式。vim
下圖爲單向主從複製架構邏輯圖,此架構只能在 Master 端進行數據寫入:centos
下圖爲雙向主主複製邏輯架構圖,此架構能夠在 Master1 端或 Master2 端進行數據寫入,或者兩端同時寫入數據(須要特殊設置)。服務器
下圖爲線性級聯單向雙主複製邏輯架構圖,此架構只能在 Master1 端進行數據寫入,工做場景中,Master1 和 Master2 做爲主主互備,Slave1 做爲從庫,中間的 Master2 須要作特殊的設置。網絡
下圖爲環狀級聯單向多主同步邏輯架構圖,任意一個點均可以寫入數據,此架構比較複雜,屬於極端環境下的「做品」,通常場景應慎用。架構
提示:在當前的生產環境中,MySQL 主從複製都是異步的複製方式,即不是嚴格實時的數據同步,可是正常狀況下給用戶的體驗是實時的。
1.3 MySQL 主從複製的企業應用場景
MySQL 主從複製集羣功能使得 MySQL 數據庫支持大規模高併發讀寫成爲可能,同時有效地保護了物理服務器宕機場景的數據備份。
應用場景1:從服務器做爲主服務器的實時數據備份。
應用場景2:主從服務器實現讀寫分離,從服務器實現負載均衡。
應用場景3:把多個從服務器根據業務重要性進行拆分訪問。
1.4 實現 MySQL 主從讀寫分離的方案
① 經過程序實現讀寫分離(性能和效率最佳,推薦):
PHP 和 JAVA 程序均可以經過設置多個鏈接文件輕鬆地實現對數據庫的讀寫分離,即當語句關鍵字爲 select 時,就去找讀庫的鏈接文件,若爲 update、insert、delete 時,則鏈接寫庫的鏈接文件。
經過程序實現讀寫分離的缺點就是須要開發人員對程序進行改造,使其對下層不透明,但這種方式更容易開發和實現,適合互聯網業務場景。
② 經過開源的軟件實現讀寫分離:
MYSQL-proxy、Amoeba 等代理軟件也能夠實現讀寫分離,可是這些軟件的穩定性和功能通常,不建議生產場景使用。絕大多數公司經常使用的仍是在應用端開發程序實現讀寫分離。
③ 大型門戶獨立開發 DAL 層綜合軟件;
2. MySQL 主從複製原理
2.1 MySQL 主從複製原理介紹
MySQL 的主從複製是一個異步的複製過程(雖然通常狀況下感受是實時的),數據將從一個 MySQL 數據庫(Master)複製到另外一個 MySQL 數據庫(Slave),在 Master 和 Slave 之間實現整個主從複製的過程是由三個線程參與完成的,其中有兩個線程(SQL 和 I/O )在 Slave 端,另外一個線程(I/O)在 Master 端。
要實現 MySQL 的主從複製,首先必須打開 Master 端的 binlog 記錄功能,不然就沒法實現,由於整個複製過程實際上就是 Slave 從 Master 獲取 binlog 日誌,而後再在 Slave 上以相同順序執行獲取的 binlog 日誌中所記錄的各類 SQL 操做。MySQL 的 binlog 功能在 /etc/my.cnf 中的 [mysqld] 模塊下增長 log-bin 參數來實現。
2.2 MySQL 主從複製過程原理詳細描述
① 在 Slave 服務器上執行 start slave 命令開啓主從複製開關,開始進行主從複製。
② 此時 Slave 服務器的 I/O 線程會經過在 Master 上已經受權的複製用戶權限請求鏈接 Master 服務器,並請求 Master 從指定 binlog 日誌文件的指定位置(日誌文件名和位置就是在配置主從服務時執行 change master 命令指定的)發送 binlog 日誌內容。
③ Master 服務器接收到來自 Slave 服務器的 I/O 線程的請求後,其上負責複製的 I/O 線程會根據 Slave 服務器的 I/O 線程請求的信息分批讀取指定 binlog 日誌文件指定位置以後的 binlog 日誌信息,而後返回給 Slave 端的 I/O 線程,返回的信息中除了 binlog 日誌內容外,還有在 Master 服務器端記錄的新的 binlog 文件名稱,以及在新的 binlog 中的下一個指定更新位置。
④ 當 Slave 服務器的 I/O 線程獲取到 Master 服務器上 I/O 線程發送的日誌內容、日誌文件及位置點後,會將 binlog 日誌內容依次寫到 Slave 端自身的 Relay Log(中繼日誌)文件的最末端,並將新的 binlog 文件名和位置記錄到 master-info文件中,以便下一次讀取 Master 端新 binlog 日誌時可以告訴 Master 服務器重新 binlog 日誌的指定文件及位置開始請求新的 binlog 日誌內容。
⑤ Slave 服務器端的 SQL 線程會實時檢測本地 Relay Log 中 I/O 線程新增長的日誌內容,而後及時地把 Relay Log 文件中的內容解析成 SQL 語句,並在自身 Slave 服務器上按解析 SQL 語句的位置順序執行應用這些 SQL 語句,並在 relay-log.info 中記錄當前應用中繼日誌的文件名及位置點。
⑥ 通過了上面的過程,就能夠確保在 Master 端和 Slave 端執行了一樣的 SQL 語句。當複製狀態正常時,Master 端和 Slave 端的數據是徹底同樣的。固然,MySQL 的複製機制也有一些特殊狀況,詳情查看官方手冊。
2.3 MySQL 主從複製重點小結
① 主從複製是異步的邏輯的 SQL 語句級的複製;
② 複製時,主庫有一個 I/O 線程,從庫有兩個線程,及 I/O 和 SQL 線程;
③ 實現主從複製的必要條件是主庫要開啓記錄 binlog 的功能;
④ 做爲複製的全部 MySQL 節點的 server-id 都不能相同;
⑤ binlog 文件只記錄對數據內容有更改的 SQL 語句,不記錄任何查詢語句。
2.4 MySQL 主從複製過程原理邏輯圖
3. MySQL 主從複製實戰
3.1 數據庫環境準備
主從複製的搭建能夠用兩臺 MySQL 服務器或者一臺 MySQL 多實例服務器完成,這裏以一臺有兩個實例的 MySQL 數據庫服務器來完成。
通常作主從複製,主從服務器在不一樣的機器上,而且監聽的端口均爲默認的 3306。
3.2 檢查及準備環境
[root@centos ~]# ll /data
drwxr-xr-x 3 mysql mysql 4096 Apr 7 10:12 3306
drwxr-xr-x 3 mysql mysql 4096 Apr 7 17:38 3307
[root@centos ~]# /data/3306/mysql start
[root@centos ~]# /data/3307/mysql start
[root@centos ~]# ss -lnt|grep 330
LISTEN 0 128 *:3306 *:*
LISTEN 0 128 *:3307 *:*
定義監聽 3306 端口的實例爲 Master 主庫。
定義監聽 3307 端口的實例爲 Slave 從庫。
3.3 主庫上的操做
[root@centos ~]# vi /data/3306/my.cnf # 編輯 3306 實例的配置文件。
[root@centos ~]# egrep "log-bin|server-id" /data/3306/my.cnf
log-bin = /data/3306/mysql-bin # 打開 binlog 日誌功能。
server-id = 1
[root@centos ~]# /data/3306/mysql restart
注意上面兩個參數的位置:
[mysqld]
server-id = 1
log-bin = /data/3306/mysql-bin
查看上面配置是否生效:
[root@centos ~]# ll /data/3306/ # 有以下內容表示生效。
-rw-rw---- 1 mysql mysql 126 Apr 7 02:19 mysql-bin.000001
-rw-rw---- 1 mysql mysql 264 Apr 7 03:17 mysql-bin.000002
-rw-rw---- 1 mysql mysql 126 Apr 7 03:52 mysql-bin.000003
-rw-rw---- 1 mysql mysql 252 Apr 7 10:12 mysql-bin.index
[root@centos ~]# mysql -uroot -p'123456' -S /data/3306/mysql.sock -e "show variables like 'log_bin';" # 能夠看到 binlog 功能生效。
| Variable_name | Value |
| log_bin | ON |
查看從庫配置:
[root@centos ~]# egrep "log-bin|server-id" /data/3307/my.cnf
#log-bin = /data/3307/mysql-bin # 不作級聯的話從庫 binlog 功能是否開啓都不影響主庫。
server-id = 3 # 兩個 id 要不一樣。
創建用於同步的帳號 rep :
[root@centos ~]# mysql -uroot -p'123456' -S /data/3306/mysql.sock # 登陸 3306。
mysql> grant replication slave on *.* to 'rep'@'192.168.136.%' identified by '123456';
mysql> flush privileges ;
提示:replication slave 爲 mysql 同步的必須權限,此處不要受權 all。
在主庫上作備份:
mysql> flush table with read lock; # 在主庫上給全部表加只讀鎖。
mysql> show master status;
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
| mysql-bin.000009 |335 | | |
mysql> show master logs; # 輸出略略略。
[root@centos ~]# mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B --events >/opt/rep.sql
[root@centos ~]# mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B --events --master-data=2 >/opt/rep.sql
[root@centos ~]# vim /opt/rep.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000009', MASTER_LOG
_POS=335;
mysql> unlock tables; # 打開只讀鎖。
mysql> show master status; # 備份完畢查看是否有變化,確保鎖表成功。
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
| mysql-bin.000009 |335 | | |
提示:上面是官方文檔給的備份方式,生產場景中的備份經常使用 -x 參數鎖表,用 --master-data 參數記錄 binlog 的文件及位置。
3.4 從庫上的操做
把上面的備份數據放入從庫
[root@centos ~]# mysql -uroot -p'oldboy123' -S /data/3307/mysql.sock </opt/rep.sql
[root@centos ~]# mysql -uroot -p'oldboy123' -S /data/3307/mysql.sock # 登陸到 3307。
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.136.141',
-> MASTER_PORT=3306,
-> MASTER_USER='rep',
-> MASTER_PASSWORD='123456',
-> MASTER_LOG_FILE='mysql-bin.000009',
-> MASTER_LOG_POS=335;
[root@centos data]# cd /data/3307/data
[root@centos data]# ll
-rw-rw---- 1 mysql mysql 80 Apr 7 18:49 master.info
[root@centos data]# cat master.info # 上面的 change 語句結果會放到 master.info 裏面。
18
mysql-bin.000009
335
192.168.136.141
rep
123456
3306
60
mysql> start slave; # 打開從庫兩個線程的開關。
Query OK, 0 rows affected (0.10 sec)
mysql> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
3.5 主從複製配置完成後檢查(主庫寫入數據看從庫)
[root@centos ~]# mysql -uroot -p'123456' -S /data/3306/mysql.sock # 登陸主庫。
mysql> create database oldboy; # 建立 oldboy 庫。
[root@centos ~]# mysql -uroot -p'oldboy123' -S /data/3307/mysql.sock # 登陸從庫。
mysql> show databases; #查看 Master 中的 oldboy 庫是否同步到 Slave。(成功)。
| Database |
| information_schema |
| mysql |
| oldboy |
| performance_schema |
| test |
[root@centos 3307]# ll
total 44
drwxr-xr-x 6 mysql mysql 4096 Apr 7 19:06 data
-rw-r--r-- 1 mysql mysql 1901 Apr 6 20:05 my.cnf
-rwx------ 1 root root 1310 Apr 7 03:06 mysql
-rw-rw---- 1 mysql mysql 6 Apr 7 17:38 mysqld.pid
-rw-r----- 1 mysql root 11758 Apr 7 18:57 mysql_oldboy3307.err
srwxrwxrwx 1 mysql mysql 0 Apr 7 17:38 mysql.sock
-rw-rw---- 1 mysql mysql 150 Apr 7 18:57 relay-bin.000001
-rw-rw---- 1 mysql mysql 340 Apr 7 19:06 relay-bin.000002
-rw-rw---- 1 mysql mysql 56 Apr 7 18:57 relay-bin.index
-rw-rw---- 1 mysql mysql 53 Apr 7 19:06 relay-log.info
[root@centos 3307]# mysqlbinlog relay-bin.000002
create database oldboy # 可看到從庫裏的建庫語句。
[root@centos 3307]# cat relay-bin.index
/data/3307/relay-bin.000001
/data/3307/relay-bin.000002
[root@centos 3307]# cat relay-log.info
/data/3307/relay-bin.000002
340 # relay log 的位置。
mysql-bin.000009
422 # 從庫 I/O 線程取 binlog 的位置。
[root@centos 3307]# cat data/master.info # 從庫 I/O 線程取 binlog 的位置。
mysql-bin.000009
422
4. MySQL 主從複製配置步驟小結
4.1 MySQL 主從複製配置完整步驟以下
① 準備兩臺數據庫環境或單臺多實例環境,肯定能正常啓動和登陸。
② 配置 my.cnf 文件:主庫配置 log-bin 和 server-id 參數;從庫配置 server-id,該值不能和主庫及其餘從庫同樣,通常不開啓從庫 log-bin 功能。注意配置後須要重啓服務使之生效。
③ 登陸主庫,增長從庫鏈接主庫同步的帳戶,例如:rep,並受權 replication slave 同步的權限。
④ 登陸主庫,整庫鎖表 flush table with read lock(窗口關閉後即失效,超時參數設置的時間到了也失效);而後 show master status 查看 binlog 的位置狀態。
⑤ 新開窗口,Linux 命令行備份或導出原有的數據庫數據,並拷貝到從庫所在的服務器目錄。若是數據量很大,而且容許停機,可停機打包,而不用 mysqldump 。
⑥ 解鎖主庫,unlock tables;
⑦ 把主庫導出的原有數據恢復到從庫。
⑧ 根據主庫的 show master status 查看 binlog 的位置狀態,在從庫執行 change master to ... 語句驗證 rep 用戶。
⑨ 從庫開啓同步開關,start slave。
⑩ 從庫 show slave status\G,檢查同步狀態,並在主庫進行更新測試。
鎖表語句知識補充:
5.1 flush tables with read lock
5.5 flush table with read lock
4.2 MySQL 主從複製從庫 IO 線程不運行解決方案
http://www.javashuo.com/article/p-qybohloh-kx.html
緣由: 首先確認 server-id 是否惟一, mysql 有可能並無加載 my.cnf 文件中的 server-id。
解決辦法:① 修改server-id (在my.cnf 文件中) 。
② mysql> set global server_id=119; #此處的server_id的值和my.cnf裏設置的同樣。
③ mysql> start slave;
4.3 MySQL 主從複製生產實踐及排障
4.3.1 故障一:主庫 show master status 沒結果
緣由:主庫 binlog 功能開關沒開或沒生效。
[root@centos ~]# egrep "server-id|log-bin" /data/3306/my.cnf
log-bin = /data/3306/mysql-bin
server-id = 1
mysql> show variables like 'server_id';
| Variable_name | Value |
| server_id | 1 |
mysql> show variables like 'log_bin';
| Variable_name | Value |
| log_bin | ON |
提示:配置文件裏的參數和 show variables 裏的參數不同。
4.3.2 故障二:提示找不到第一個 binlog 文件
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.136.141',
-> MASTER_PORT=3306,
-> MASTER_USER='rep',
-> MASTER_PASSWORD='123456',
-> MASTER_LOG_FILE='mysql-bin.000009',
-> MASTER_LOG_POS=335;
緣由:上面一行,binlog 文件名兩端不能有空格。
4.3.3 對主數據庫鎖表只讀(當前窗口不要關掉)
5.1 flush tables with read lock
5.5 flush table with read lock
提示:在 MySQL 5.1 中,鎖表的語句是: flush tables with read lock;這個鎖表語句的時間,在不一樣引擎的狀況,會受下面參數的控制。鎖表時若是超過設置時間不操做,會自動解鎖。
interactive_timeout = 60
wait_timeout = 60
mysql> show variables like '%timeout%'; # 查看默認的鎖表超時時間。
interactive_timeout | 28800
wait_timeout | 28800
把上面兩個參數改成 60 秒:
mysql> set global wait_timeout = 60;
mysql> set global interactive_timeout = 60;
mysql> show variables like '%timeout%'; # 退出從新進入生效。
interactive_timeout | 60
wait_timeout | 60
重啓 3306 實例後失效:(由於沒有修改配置文件)
mysql> show variables like '%timeout%';
interactive_timeout | 28800
wait_timeout | 28800
因爲切換 binlog 致使 show master 位置變化無影響。(數據沒有更新)
4.4 回顧 MySQL 主從複製原理要點
① 異步方式同步;
② 邏輯同步模式,多種模式,默認是經過 SQL 語句執行;
③ 主庫經過記錄 binlog 實現對從庫的同步。binlog 記錄數據庫的更新語句。
④ 主庫一個 I/O 線程,從庫由一個 I/O 線程和一個 SQL 線程來完成;
⑤ 從庫關鍵文件 master.info 、relay-log 、relay-info 功能。
⑥ 若是從庫還想級聯從庫,須要打開 log-bin 和 log-slave-updates 參數。
4.5 企業場景快速配置 MySQL 主從複製方案
① 安裝好要配置從庫的數據庫,配置好 log-bin 和 server-id 參數;
② 無配置主庫 my.cnf 文件,主庫的 log-bin 和 server-id 參數默認就是配置好的;
③ 登錄主庫增長因爲從庫鏈接主庫同步的帳戶如 rep 並受權 replication slave 的權限;
④ 半夜使用 mysqldump 帶 --master-data=1 備份的全備數據恢復到從庫;
⑤ 在從庫執行 change master to ... 語句,無需 binlog 文件及對應位置點。
⑥ 從庫開啓同步開關,start slave;
⑦ 從庫 show slave status\G 檢查同步狀態,並在主庫進行更新測試。
4.6 主從複製過程當中的同步狀態
4.6.1 查看主庫從庫同步狀態
查看 3306 實例 Master 線程的同步狀態:
[root@centos ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
mysql> show processlist;
Master has sent all binlog to slave; waiting for binlog to be updated
查看 3307 實例 Slave 線程的同步狀態:
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock
mysql> show processlist;
Slave has read all relay log; waiting for the slave I/O thread to update it
Waiting for master to send event
4.6.2 複製主線程狀態
如下是主服務器的線程最多見狀態。若是在主副武器上沒有看到任何 binlog dump 線程說明覆制沒有運行,即沒有鏈接任何從服務器。
Sending binlog event to slave
表示線程已經從二進制日誌讀取了一個事件而且正在將它發送到從服務器。
Finished reading one binlog;swiching to next binlog
表示線程已經讀完二進制日誌文件而且正打開下一個要發送到從服務器的日誌文件。
Has sent all binlog to slave;waiting for binlog to be updated
表示線程已經把全部更新的 binlog 內容發給從庫,目前正在等待 binlog 的更新。
Waiting to finalize termination
表示線程中止時發生的一個很簡單的狀態。
4.6.3 複製從 I/O 線程狀態
Connection to master
線程正試圖鏈接主服務器。
Checking master version
創建主從服務器之間的鏈接後當即臨時出現的狀態。
Registering slave on master
創建主從服務器之間的鏈接後當即臨時出現的狀態。
Registering binlog dump
創建主從服務器之間的鏈接後當即臨時出現的狀態。線程向主服務器發送一條請求,索取從請求的二進制日誌文件名和位置開始的二進制日誌的內容。
Waiting to reconnect after a failed binlog dump request
若是二進制日誌轉儲請求失敗(因爲沒有鏈接),線程進入睡眠狀態,而後按期嘗試從新鏈接,可使用 --master-connect-retry 選項指定重試之間的間隔。
Reconnecting after a failed binlog dump request
線程正嘗試從新鏈接服務器。
Waiting for master to send event
線程已經鏈接上主服務器,正等待二進制日誌事件到達。若是主服務器正空閒,會持續較長的時間,若是等待持續 slave_read_timeout 秒,則發生超時。此時,線程認爲鏈接被中斷並企圖從新鏈接。
Queueing master event to the relay log
線程已經讀取一個事件,正將它複製到中繼日誌供 SQL 線程來處理。
4.6.4 複製從 SQL 線程狀態
Reading event from the relay log
線程已經從中繼日誌讀取一個事件,能夠對事件進行處理了。
Slave has read all relay log; waiting for the slave I/O thread to update it
線程已經處理了中繼日誌文件中的全部事件,如今正等待 I/O 線程將新事件寫入中繼日誌。
Waiting for slave mutex on exit
線程中止時發生的一個很簡單的狀態。
4.7 查看 MySQL 線程同步狀態的用途
經過 MySQL 線程同步狀態查看數據庫同步是否完成,用於主庫宕機或者人工數據庫主從切換遷移等。主庫宕機選擇最快的從庫提高爲主,就須要查看線程狀態,固然也能夠利用 MySQL 的半同步功能,選擇固定的庫提高爲主。
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock
mysql> show slave status\G
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.136.141
Master_User: rep
Master_Port: 3306
Connect_Retry: 60 # 鏈接重試。
Master_Log_File: mysql-bin.000011
Read_Master_Log_Pos: 107
Relay_Log_File: relay-bin.000008
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000011
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 上面兩個參數的 yes 表示同步的狀態是 OK 的,可是是否有延遲等沒法體現出來。
Last_Errno: 0 # 若是報錯,該參數會有數字提示碼。
Last_Error:
Seconds_Behind_Master: 0 # 從庫落後於主庫的秒數。參考,不絕對準確。
Master_SSL_Verify_Server_Cert: No
Master_Server_Id: 1
5. MySQL 常見錯誤碼及解釋
1005:MYSQL建立表失敗
1006:MYSQL建立數據庫失敗
1007:MYSQL數據庫已存在,建立數據庫失敗
1008:MYSQL數據庫不存在,刪除數據庫失敗
1009:MYSQL不能刪除數據庫文件致使刪除數據庫失敗
1010:MYSQL不能刪除數據目錄致使刪除數據庫失敗
1011:MYSQL刪除數據庫文件失敗
1012:MYSQL不能讀取系統表中的記錄
1016:文件沒法打開,使用後臺修復或者使用 phpmyadmin 進行修復。
1017:服務器非法關機,致使該文件損壞。
1020:MYSQL記錄已被其餘用戶修改
1021:硬盤剩餘空間不足,請加大硬盤可用空間
1022:MYSQL關鍵字重複,更改記錄失敗
1023:MYSQL關閉時發生錯誤
1024:MYSQL讀文件錯誤
1025:MYSQL更更名字時發生錯誤
1026:MYSQL寫文件錯誤
1030:多是服務器不穩定。(具體緣由不是很清楚)
1032:MYSQL記錄不存在
1036:MYSQL數據表是隻讀的,不能對它進行修改
1037:系統內存不足,請重啓數據庫或重啓服務器
1038:MYSQL用於排序的內存不足,請增大排序緩衝區
在my.ini 修改成max_connections=1000或更大,重啓mysql
1041:系統內存不足
1042:無效的主機名
1043:無效鏈接
1044:MYSQL當前用戶沒有訪問數據庫的權限
1045:MYSQL不能鏈接數據庫,服務器、數據庫名、用戶名或密碼錯誤
6. MySQL 主從複製讀寫分離受權多種方案
6.1 生產受權方案一
主庫:web oldboy123 10.0.0.1 3306 (select、insert、delete、update)
從庫:將主庫的 web 用戶同步到從庫,而後回收 insert、delete、update 權限。
不收回權限的解決辦法:
不收回從庫權限,在 my.cnf 裏面設置 read-only 參數或指定 read-only 只讀啓動。
開發登錄數據庫(主從的用戶密碼一致):
web oldboy123 10.0.0.1 3306 (select、insert、delete、update)
web oldboy123 10.0.0.2 3306 (select)
6.2 生產受權方案二
主庫:web_w oldboy123 10.0.0.1 3306 (select、insert、delete、update)
從庫:web_r oldboy123 10.0.0.2 3306 (select)
風險:web_w 用戶鏈接從庫寫數據!
解決上述風險的方法:
設置 read-only 參數或指定 read-only 只讀。
開發登錄數據庫:多套用戶密碼,不專業。
生產受權方案三:【推薦】
不一樣步 mysql 庫:主從庫分別進行以下受權:
主庫:web oldboy123 10.0.0.1 3306 (select、insert、delete、update)
從庫:web oldboy123 10.0.0.2 3306 (select)
從庫設置 read-only 參數讀,增長雙保險。
缺陷:
當從庫切換主庫時,鏈接用戶會有權限問題。
解決方法:(百度架構方案)
保留一個從庫專門準備接替主庫。
6.3 忽略 MySQL 主從複製主庫受權表同步實戰
[root@centos ~]# vi /data/3306/my.cnf # 添加以下四行。
#replicate-ignore-db = mysql
#binlog-ignore-db = mysql
#binlog-ignore-db = performance_schema
#binlog-ignore-db = information_schema
[root@centos ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
mysql> create user oldgirl@localhost identified by 'old123';
# 登陸 3306 建立用戶 oldgirl@localhost 。
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock
mysql> select user,host from mysql.user;
oldgirl | localhost
# 登陸 3307 查看用戶: oldgirl@localhost 存在【說明主從同步了】。
去掉上面的註釋,並重啓 3306 數據庫:
[root@centos ~]# grep ignore-db /data/3306/my.cnf
replicate-ignore-db = mysql
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = information_schema
[root@centos ~]# /data/3306/mysql restart
Stopping MySQL...
Starting MySQL...
此時,在主庫上建立新的用戶後,再到從庫查看,新建的用戶不會同步。
mysql> show slave status\G # 肯定是在主從同步正常的前提下不一樣步用戶的。
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
6.4 Replication 中可經過如下選項減小 binlog 數據量
Master 端:
--binlog-do-db 二進制日誌記錄的數據庫(多個庫用逗號分隔)。
--binlog-ignore-db 二進制日誌忽略的數據庫(多個庫用逗號分隔)。
Slave 端:
--replication-do-db 設定須要複製的數據庫。
--replication-ignore-db 設定忽略複製的數據庫。
--replication-do-table 設定須要複製的數據表。
--replication-ignore-table 設定忽略複製的數據表。
--replication-wild-do-table 同 --replication-do-table ,可是可加通配符。
--replication-wild-ignore-table 同 --replication-ignore-table ,可是可加通配符。
經過 read-only 參數防止數據寫從庫的方法:
在從庫上設置 read-only 參數或者直接帶 --read-only 參數啓動或重啓數據庫。
① 在 my.cnf 裏 [mysqld] 模塊下加 read-only 參數並重啓數據庫:
[mysqld]
read-only
② 直接帶 --read-only 參數啓動或重啓數據庫:
mysqld_safe --default-file=/data/3307/my.cnf --read-only &
測試從庫是否只讀:
[root@centos ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock # 登陸 3306.
mysql> show databases;
| Database |
| information_schema |
| mysql |
| oldboy |
| performance_schema |
| test |
mysql> drop database test; # 刪除 test 庫。
mysql> Bye
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock # 登陸 3307 。
mysql> show databases; # 可看到 test 庫已刪除(表示同步正常)。
| Database |
| information_schema |
| mysql |
| oldboy |
| performance_schema |
mysql> create database test; # 在從庫可建庫,這是爲何?!
Query OK, 1 row affected (0.00 sec)
提示:因爲從庫設置了 read-only,非 SUPER 權限是沒法寫入的,root 用戶有 SUPER 權限,因此依舊能夠在配置 read-only 的從庫寫入數據。建立非 SUPER 權限的用戶測試:
mysql> grant select,insert,update,delete on *.* to leilei@localhost identified by '123456';
# 建立用戶受權增刪改查。
mysql> flush privileges;
[root@centos ~]# mysql -uleilei -p123456 -S /data/3307/mysql.sock
mysql> select user();
| user() |
| leilei@localhost |
mysql> use test;
mysql> create table t(id int); # 沒法建表(提示 read-only)
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
測試結論:
① 若想要從庫只讀,前提是主從同步正常。
② 在 my.cnf 裏的 [mysqld] 模塊下加入 read-only 參數後重啓服務才能生效。
③ root 用戶及 ALL 權限的用戶能夠插入及刪除數據。
④ 具有 insert、update、delete 權限的用戶沒法經過 read-only 的限制。
7. 生產案例:MySQL 從庫數據衝突致使同步中止
7.1 模擬錯誤,重現問題
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock # 登陸從庫。
mysql> create database butongbu; # 建立 butongbu 庫。
mysql> show databases;
| butongbu |
| mysql |
| oldboy |
mysql> show slave status\G # 檢查同步狀態(正常)。
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@centos ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
mysql> create database butongbu; # 在主庫建立同名的庫。
Query OK, 1 row affected (0.00 sec)
登陸從庫便可看到出現的錯誤:
[root@centos ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock
mysql> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1007
Last_Error: Error 'Can't create database 'butongbu'; database exists' on query. Default database: 'butongbu'. Query: 'create database butongbu'
MySQL 錯誤代號1007: MYSQL數據庫已存在,建立數據庫失敗。
7.2 解決上述問題
7.2.1 方法一:添加忽略衝突次數爲 1 忽略
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> set global sql_slave_skip_counter = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G # 能夠看到主從同步恢復正常了。
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_Errno: 0
① 對於普通的互聯網業務,忽略問題不是很大,固然要確認不影響公司業務的前提下。
② 企業場景解決主從同步,比主從不一致更重要。若是主從數據一致也很重要,再找時間恢復從庫。
③ 主從數據不一致和保持主從同步持續狀態哪一個更總要須要根據不一樣業務選擇。
7.2.2 方法二:經過忽略錯誤號跳過指定的錯誤
[root@centos ~]# vi /data/3307/my.cnf
[root@centos ~]# grep slave-skip /data/3307/my.cnf
slave-skip-errors = 1032,1062,1007
[root@centos ~]# /data/3307/mysql stop
[root@centos ~]# /data/3307/mysql start
此時主庫建立從庫已經存在的數據庫,就不會產生不一樣步的問題(忽略 1007 錯誤)。
8. 從庫開啓 binlog 緣由及開啓實戰講解
8.1 須要記錄 binlog 的狀況
① 當前主庫還要做爲其餘從庫的主庫,也就是級聯同步,須要開啓 binlog;
② 把從庫做爲備份服務器時須要開啓 binlog。
8.2 實踐操做:在從庫添加以下參數
[root@centos ~]# vi /data/3307/my.cnf
#log-bin = /data/3307/mysql-bin
#log-slave-updates
#expire_logs_days = 7
8.3 重啓生效:
[root@centos ~]# /data/3307/mysql stop
[root@centos ~]# /data/3307/mysql start
9. 企業場景一主多從主庫宕機,切換從庫爲主庫繼續主從同步過程詳解
9.1 主庫 master 宕機,登錄從庫查看兩個線程的更新狀態
mysql> show processlist;
State:Waiting for master to send event # IO 線程。
State:Has read all relay log;waiting for the slave I/O thread to update it # SQL 線程。
提示:上面的狀態說明該從庫是和主庫同步的,或者說是最新的。
9.2 工做中肯定將哪一個從庫提高爲主庫的方法
cat /data/3307/data/master.info
cat /data/3308/data/master.info
① 確保更新完畢,看看從庫哪一個最快,通過測試沒有延遲的狀況 POS 差距很小,甚至是一致的。經過查看 master.info 的內容來肯定將哪一個(數據最新,跟主庫一致性更高的)從庫提高爲主庫。
② 其餘方法:利用半同步的功能,直接選擇作了實時同步的從庫(太子)。
③ 提示:若是主庫只是服務宕機,服務器正常,能夠將主庫服務器的 binlog 拉倒要提高爲主庫的從庫,用來補全數據。
9.3 開始切換選擇的從庫爲主庫
① 確保全部 relay log 所有更新完畢:
在每一個從庫上執行 stop slave io_thread;show processlist;直到看到 Slave has read all relay log 表示從庫更新都執行完畢。
② 登陸選定的從庫執行以下操做:
stop slave;
retset master;
quit;
還要受權同步用戶 rep 和本來來的主庫同樣。
提示:若是提高爲主庫的從庫存在忽略受權表,read-only 等設置,須要清理這些設置。
③ 進入到數據庫目錄,刪除 master.info、relay-log.info
提示:檢查受權表,read-only 等參數。
④ 編輯該從庫的配置文件:
開啓 log-bin 參數,若是存在 log-slave-updates、read-only 等必定要註釋掉,重啓後提高主庫完畢。
⑤ 若是主庫服務器沒有宕機,須要去主庫拉取 binlog 補全提高主庫的從庫數據。
⑥ 其餘從庫操做:
前提檢查提高爲主庫的從庫中同步用戶 rep 已經存在。
登陸從庫:
stop slave;
change master to master_host = '192.168.136.152'; # 若是數據不一樣步就指定位置點。
start slave;
show slave status\G
⑦ 修改程序配置文件從主庫指向從庫、平時訪問數據庫用域名則可直接改 hosts 解析。
⑧ 修改損壞的主庫,做爲從庫或從新切換爲主庫。
10. MySQL 5.5 以上支持半同步
半同步下的一主多從恢復,直接對設置半同步的從庫肯定爲主庫。讓某一個穩定的從庫和主庫徹底一致,即主庫和這個從庫都更新數據完畢後再返回給用戶更新數據成功的消息。
半同步的優勢:
確保至少一個從庫和主數據庫一致。
半同步的缺點:
主從之間網絡延遲,或者從庫有問題的時候會下降用戶體驗。(可設置超時時間爲10秒)。