目錄:
mysql主從同步定義
主從同步機制
配置主從同步
配置主服務器
配置從服務器
使用主從同步來備份
使用mysqldump來備份
備份原始文件
主從同步的小技巧
排錯
Slave_IO_Running: NO
Slave_SQL_Running: No
mysql主從同步定義
主從同步使得數據可以從一個數據庫服務器復制到其他服務器上,在復制數據時,一個服務器充當主服務器(master),其余的服務器充當從服務器(slave)。因為復制是異步進行的,所以從服務器不需要一直連接着主服務器,從服務器甚至可以通過撥號斷斷續續地連接主服務器。通過配置文件,可以指定復制所有的數據庫,某個數據庫,甚至是某個數據庫上的某個表。
使用主從同步的好處:
- 通過增加從服務器來提高數據庫的性能,在主服務器上執行寫入和更新,在從服務器上向外提供讀功能,可以動態地調整從服務器的數量,從而調整整個數據庫的性能。
- 提高數據安全-因為數據已復制到從服務器,從服務器可以終止復制進程,所以,可以在從服務器上備份而不破壞主服務器相應數據
- 在主服務器上生成實時數據,而在從服務器上分析這些數據,從而提高主服務器的性能
注意,mysql是異步復制的,而MySQL Cluster是同步復制的。有很多種主從同步的方法,但核心的方法有兩種,Statement Based Replication(SBR)基於SQL語句的復制,另一種是Row Based Replication(RBR)基於行的復制,也可以使用Mixed Based Replication(MBR)。在mysql5.6中,默認使用的是SBR。而mysql 5.6.5和往后的版本是基於global transaction identifiers(GTIDs)來進行事務復制。當使用GTIDs時可以大大簡化復制過程,因為GTIDs完全基於事務,只要在主服務器上提交了事務,那么從服務器就一定會執行該事務。
通過設置服務器的系統變量binlog_format來指定要使用的格式:
1.SBR:當使用二進制日志時,主服務器會把SQL語句寫入到日志中,然后從服務器會執行該日志,這就是SBR,在mysql5.1.4之前的版本都只能使用這種格式。使用SBR會有如下
長處:
- 日志文件更小
- 記錄了所有的語句,可以用來日后審計
弊端:
- 使用如下函數的語句不能被正確地復制:load_file(); uuid(), uuid_short(); user(); found_rows(); sysdate(); get_lock(); is_free_lock(); is_used_lock(); master_pos_wait(); rand(); release_lock(); sleep(); version();
- 在日志中出現如下警告信息的不能正確地復制:[Warning] Statement is not safe to log in statement format.
- 或者在客戶端中出現show warnings
- Insert … select語句會執行大量的行級鎖表
- Update語句會執行大量的行級鎖表來掃描整個表
2.RBR:主服務器把表的行變化作為事件寫入到二進制日志中,主服務器把代表了行變化的事件復制到從服務中,使用RBR的
長處:
- 所有的數據變化都是被復制,這是最安全的復制方式
- 更少的行級鎖表
弊端:
- 日志會很大
- 不能通過查看日志來審計執行過的sql語句,不過可以通過使用mysqlbinlog
- --base64-output=decode-rows --verbose來查看數據的 變動
3.MBR:既使用SBR也使用RBR,默認使用SBR
主從同步機制
Mysql服務器之間的主從同步是基於二進制日志機制,主服務器使用二進制日志來記錄數據庫的變動情況,從服務器通過讀取和執行該日志文件來保持和主服務器的數據一致。
在使用二進制日志時,主服務器的所有操作都會被記錄下來,然后從服務器會接收到該日志的一個副本。從服務器可以指定執行該日志中的哪一類事件(譬如只插入數據或者只更新數據),默認會執行日志中的所有語句。
每一個從服務器會記錄關於二進制日志的信息:文件名和已經處理過的語句,這樣意味着不同的從服務器可以分別執行同一個二進制日志的不同部分,並且從服務器可以隨時連接或者中斷和服務器的連接。
主服務器和每一個從服務器都必須配置一個唯一的ID號(在my.cnf文件的[mysqld]模塊下有一個server-id配置項),另外,每一個從服務器還需要通過CHANGE MASTER TO語句來配置它要連接的主服務器的ip地址,日志文件名稱和該日志里面的位置(這些信息存儲在主服務器的數據庫里)
配置主從同步
有很多種配置主從同步的方法,可以總結為如下的步驟:
1.在主服務器上,必須開啟二進制日志機制和配置一個獨立的ID
2.在每一個從服務器上,配置一個唯一的ID,創建一個用來專門復制主服務器數據的賬號
3.在開始復制進程前,在主服務器上記錄二進制文件的位置信息
4.如果在開始復制之前,數據庫中已經有數據,就必須先創建一個數據快照(可以使用mysqldump導出數據庫,或者直接復制數據文件)
5.配置從服務器要連接的主服務器的IP地址和登陸授權,二進制日志文件名和位置
配置主服務器
1.更改配置文件,首先檢查你的主服務器上的my.cnf文件中是否已經在[mysqld]模塊下配置了log-bin和server-id
[mysqld] log-bin=mysql-bin server-id=1
注意上面的log-bin和server-id的值都是可以改為其他值的,如果沒有上面的配置,首先關閉mysql服務器,然后添加上去,接着重啟服務器
2.創建用戶,每一個從服務器都需要用到一個賬戶名和密碼來連接主服務器,可以為每一個從服務器都創建一個賬戶,也可以讓全部服務器使用同一個賬戶。下面就為同一個ip網段的所有從服務器創建一個只能進行主從同步的賬戶。
首先登陸mysql,然后創建一個用戶名為rep,密碼為123456的賬戶,該賬戶可以被192.168.253網段下的所有ip地址使用,且該賬戶只能進行主從同步
mysql > grant replication slave on *.* to ‘rep’@‘192.168.253.%’ identified by ‘123456’;
3.獲取二進制日志的信息並導出數據庫,步驟:
首先登陸數據庫,然后刷新所有的表,同時給數據庫加上一把鎖,阻止對數據庫進行任何的寫操作
mysql > flush tables with read lock;
然后執行下面的語句獲取二進制日志的信息
mysql > show master status;
File的值是當前使用的二進制日志的文件名,Position是該日志里面的位置信息(不需要糾結這個究竟代表什么),記住這兩個值,會在下面配置從服務器時用到。
注意:如果之前的服務器並沒有配置使用二進制日志,那么使用上面的sql語句會顯示空,在鎖表之后,再導出數據庫里的數據(如果數據庫里沒有數據,可以忽略這一步)
[root@localhost backup]# mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases > /server/backup/mysql_bak.$(date +%F).sql
如果數據量很大,可以在導出時就壓縮為原來的大概三分之一
[root@localhost backup]# mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases | gzip > /server/backup/mysql_bak.$(date +%F).sql.gz
這時可以對數據庫解鎖,恢復對主數據庫的操作
mysql > unlock tables;
配置從服務器
首先檢查從服務器上的my.cnf文件中是否已經在[mysqld]模塊下配置leserver-id
[mysqld]
server-id=2
注意上面的server-id的值都是可以改為其他值的(建議更改為ip地址的最后一個字段),如果沒有上面的配置,首先關閉mysql服務器,然后添加上去,接着重啟服務器
如果有多個從服務器上,那么每個服務器上配置的server-id都必須不一致。從服務器上沒必要配置log-bin,當然也可以配置log-bin選項,因為可以在從服務器上進行數據備份和災難恢復,或者某一天讓這個從服務器變成一個主服務器
如果主服務器導出了數據,下面就導入該文件,如果主服務器沒有數據,就忽略這一步
[root@localhost ~]# mysql -uroot -p'123456' -S /data/3306/data/mysql.sock < /server/backup/mysql_bak.2015-07-01.sql
如果從主服務器上拿過來的是壓縮文件,就先解壓再導入
配置同步參數,登陸mysql,輸入如下信息:
mysql> CHANGE MASTER TO -> MASTER_HOST='master_host_name', -> MASTER_USER='replication_user_name', -> MASTER_PASSWORD='replication_password', -> MASTER_LOG_FILE='recorded_log_file_name',
如圖所示:
啟動主從同步進程
mysql > start slave;
檢查狀態
mysql > show slave status \G
上面的兩個進程都顯示YES則表示配置成功
使用主從同步來備份
把主服務器的數據復制到從服務器上,然后備份從服務器的數據,在數據量不是很大的時候使用mysqldump命令,對於很大的數據庫,就直接備份數據文件。
使用mysqldump來備份
步驟:(以下的所有操作都在從服務器上進行)
1.首先暫停從服務器的復制進程
shell > mysqladmin stop-slave
或者只是暫停SQL進程(從服務器仍然能接收二進制日志的事件,但不會執行這些事件,這樣能在重啟SQL進程時加快復制進度)
shell > mysql -e ‘stop slave sql_thread;’
2.使用mysqldump導出全部或部分的數據庫
shell > mysqldump --all-databases > fulldb.dump
3.在導出數據庫后,重啟復制進程
shell > mysqladmin start-slave
備份原始文件
為了保證數據文件的完整性,在備份之前首先關閉從服務器,步驟:
1.關閉從服務器:
shell > mysqladmin shutdown
2.復制數據文件,可以使用壓縮命令,假如當前目錄就是數據庫的數據目錄(在my.cnf文件中的配置項datadir的值就是該目錄的位置)
shell > tar cf /tmp/dbbackup.tar ./data
3.然后再啟動mysql服務器
主從同步的小技巧
主服務器第一次導入數據,如果你從其他地方拿來了要導入到主服務器中的數據,此時只要在主服務器中導入一次即可,因為這些數據會自動發送到從服務器中,在主服務器上使用命令
shell > mysql -h master < other_data.sql
增加從服務器,本來已經至少有一個從服務器時(暫時命名為slave1),決定再添加其余的從服務器(slave2),此時就不需要像上面那樣去操作主服務器,只要復制一個已經存在的從服務器就可以了
排錯
Slave_IO_Running: NO
這是一個很常見的錯誤(我也曾對這個錯誤咬牙切齒),總結起來就三個原因:
- 主服務器的網絡不通,或者主服務器的防火牆拒絕了外部連接3306端口
- 在配置從服務器時,輸錯了ip地址和密碼,或者主服務器在創建用戶時寫錯了用戶名和密碼
- 在配置從服務器時,輸錯了主服務器的二進制日志信息
排錯過程:(主服務器ip:192.168.1.139,從服務器ip:192.168.1.204)
第0步就是檢查錯誤日志,如果不能快速排錯,可以按我的步驟試試:
1.首先在從服務器上執行ping程序,確定能ping通主服務器
在從服務器上執行mysq的遠程連接
[root@slave204 log]# mysql -urep -p -h 192.168.1.139 -P3306
如果顯示ERROR 1045 (28000): Access denied for user 'test'@'192.168.1.204' (using password: YES)則跳轉到第3
2.登陸主服務器的mysql,查看所有的用戶
mysql > select user,host from mysql.user;
上圖就是我的錯誤根源,可以看到用戶名完全寫錯了,先刪除錯誤的用戶:
mysql > drop user “rep@192.168.1.%”@”%”;
再重新創建用戶:
mysql > grant replication slave on *.* to ‘rep’@‘192.168.1.%’ identified by ‘123456’;
mysql > flush privileges;
3.假如用戶名沒有錯,那么如何排除是否是輸入的密碼錯誤呢?
額,我也想知道方法。最好就是多輸入幾遍,或者重新創建用戶名和密碼來測試。問題還沒有解決,轉到4
4.在你的防火牆中添加3306端口
[root@localhost mysql]# firewall-cmd --zone=public --add-port=3306/tcp --permanent [root@localhost mysql]# firewall-cmd --reload
再關閉selinux
[root@slave204 log]# vi /etc/sysconfig/selinux
把SELINUX=enforcing改為SELINUX=disabled
[root@slave204 log]# source /etc/sysconfig/selinux
登錄主服務器,查看服務器狀態
mysql > show master status \G
然后重新配置一次從服務器,在配置之前首先關閉主從同步進程
mysql > stop slave;
之外的方法,我也沒試過
Slave_SQL_Running: No
把上面的Slave_IO_Running調試成YES后,就輪到這個小樣了。我根據這個博客的內容來解決的:http://kerry.blog.51cto.com/172631/277414