Mysql主主復制
MySQL主主復制結構區別於主從復制結構。在主主復制結構中,兩台服務器的任何一台上面的數據庫存發生了改變都會同步到另一台服務器上,這樣兩台服務器互為主從,並且都能向外提供服務。 下面是配置步驟 需要兩台MySQL主機做服務器: MySQL的創建方法參見:創建MySQL數據庫 Server-1:192.168.0.1 Server-2:192.168.0.2
一、創建並授權用戶
這一步在每一台(主)服務器上創建一個用戶,並為之授權,使它們可以互相訪問彼此的數據庫 在Server-1上: 創建一個充許Server-1來訪問的用戶server2,密碼為:server2 mysql> GRANT REPLICATION SLAVE ON *.* > TO 'server2'@'192.168.0.2' IDENTIFIED BY 'server2'; 在Server-2上: 創建一個充許Server-1來訪問的用戶server1,密碼為:server1 mysql> GRANT REPLICATION SLAVE ON *.* > TO 'server1'@'192.168.0.1' IDENTIFIED BY 'server1';
二、修改MySQL主配置文件
在MySQL的主配置文件中修改/添加如下內容: Server-1上: [mysqld] server-id = 10 log-bin = mysql-bin replicate-do-db = mydb auto-increment-increment = 2 auto-increment-offset = 1 # service mysqld restart Server-2上: [mysqld] server-id = 20 log-bin = mysql-bin replicate-do-db = mydb auto-increment-increment = 2 auto-increment-offset = 2 # service mysqld restart 注:二都只有server-id不同和 auto-increment- offset不同 auto-increment-offset是用來設定數據庫中自動增長的起點的,回為這兩能服務器都設定了一次自動增長值2,所以它們的起點必須得不同,這樣才能避免兩台服務器數據同步時出現主鍵沖突 replicate-do-db 指定同步的數據庫,我們只在兩台服務器間同步mydb數據庫 另:auto-increment-increment的值應設為整個結構中服務器的總數,本案例用到兩台服務器,所以值設為2
三、復制其中一台服務器的數據庫到別外一台服務器
這一步中誰做為源數據不重要,重要的是在正式的復制(Replication)開始之前兩台服務都能准備的反應彼此的數據。 我們可以先從源數據庫中導出數據到備份文件,這裡我們使用mysqldump命令 以Server-1上數據庫為源數據庫 備份數據前先鎖表,保證數據一致性 mysql> FLUSH TABLES WITH READ LOCK; > SHOW MASTER STATUS; +-----------------+------------+----------------+--------------------+ |File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-----------------+------------+----------------+--------------------+ |mysql-bin.000006 | 213 | | | +-----------------+------------+----------------+--------------------+ 1 row in set (0.01 sec) 該結果顯示,源服務器現在處於6號二進制文件的213位置 開始備份數據庫 # mysqldump --user=root -p mydb > /tmp/mydb.sql 備份完畢,現在可以解鎖數據庫表 mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec)
四、將備份數據導入Server-2
先在Server-2上創建一個與mydb同名的空數據庫 # mysql > CREATE DATABASE mydb; >\q # scp 192.168.0.1:/tmp/mydb.sql ./ # mysql -uroot -p mydb < /tmp/mydb.sql 此時,我們需要注意當前服務器的二進制日志的位置 # mysql > LOCK TALBES WITH READ LOCK; > SHOW MASTER STATUS; +-----------------+------------+----------------+--------------------+ |File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-----------------+------------+----------------+--------------------+ |mysql-bin.000001 | 106 | | | +-----------------+------------+----------------+--------------------+ 1 row in set (0.00 sec) > UNLOCK TABLES; > \q 五、互相通告二進制日志位置 在Server-1上: # mysql > CHANGE MASTER TO > MASTER_HOST='192.168.0.2', > MASTER_USER='master1', > MASTER_PASSWORD='master1', > MASTER_LOG_FILE='mysql-bin.000001', > MASTER_LOG_POS=106; 在Server-2上: # mysql > CHANGE MASTER TO > MASTER_HOST='192.168.0.1', > MASTER_USER='master2', > MASTER_PASSWORD='master2', > MASTER_LOG_FILE='mysql-bin.000006', > MASTER_LOG_POS=213;
六、啟動復制(Replication)功能
在兩台主機上分別執行 # mysql > START SLAVE; 配置到此完成!
測試:
在任意一台服務器上創建一個數據庫 # mysql > CREATE DATABASE repltest; > USE repltest; > CREATE TABLE test( > name char(30)); > \q # 在另一台服務器上查看數據庫信息: # mysql > SHOW DATABASES; 結果中將顯示有一個名為replrtest的數據庫
eg: 192.168.0.186 master1 192.168.0.167 master 2
MASTER 1 [mysql@master1~]$ cat /usr/local/mysql/my.cnf # For advice on how to change settings please see
[mysqld]
port=3308
skip-name-resolve
datadir=/cifpay/mysqldb
basedir=/usr/local/mysql
log-error=/cifpay/mysqldb/oracle11g.com.err
pid-file=/cifpay/mysqldb/oracle11g.com.pid
plugin-dir=/usr/local/mysql/lib/plugin
socket=/tmp/mysql.sock
# ----master-----#
server_id=1
log-bin=/cifpay/mysql-bin.log
binlog-ignore-db=mysql
auto-increment-increment=2
auto-increment-offset=1
sql-mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION ================ MASTER 2
[mysql@master2~]$ cat /usr/local/mysql/my.cnf # For advice on how to change settings please see
[mysqld]
port=3308
basedir=/usr/local/mysql
datadir=/cifpay/mysqldb
log-error=/cifpay/mysqldb/dominic.mysql1.err
pid-file=/cifpay/mysqldb/dominic.mysql1.pid
plugin-dir=/usr/local/mysql/lib/plugin
# ----master 2 -------#
server-id=2
read_only=TURE
binlog-ignore-db=mysql
#log_slave_updates=1
log-bin=/cifpay/mysql-bin.log
auto-increment-increment=2
auto-increment-offset=2
sql-mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
重啟動 MASTER 1、MASTER 2 數據庫,使配置生效:
MASTER 1 : mysql> change master to -> MASTER_HOST='192.168.0.167', -> MASTER_USER='copy1', --用戶不要一樣 -> MASTER_PASSWORD='123456', -> MASTER_LOG_FILE='mysql-bin.000002', --來自 master 2 -> MASTER_LOG_POS=753, --來自 master 2 -> MASTER_PORT=3308; Query OK, 0 rows affected, 2 warnings (0.08 sec)
mysql> start slave; Query OK, 0 rows affected (0.01 sec) mysql> SHOW SLAVE STATUS \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.167 Master_User: copy1 Master_Port: 3308 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 753 Relay_Log_File: oracle11g-relay-bin.000002 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 753 Relay_Log_Space: 460 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 Master_UUID: 9b6fc45b-81b3-11e4-95f4-0800273e24cb Master_Info_File: /cifpay/mysqldb/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 1 row in set (0.00 sec)
MASTER 2
mysql> CHANGE MASTER TO -> MASTER_HOST='192.168.0.186', -> MASTER_USER='copy2', -> MASTER_PASSWORD='123456', -> MASTER_LOG_FILE='mysql-bin.000005', --來自master 1 -> MASTER_LOG_POS=216, --來自master 1 -> MASTER_PORT=3308; ERROR 1198 (HY000): This operation cannot be performed with a running slave; run STOP SLAVE first mysql> STOP SLAVE; Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE MASTER TO -> MASTER_HOST='192.168.0.186', -> MASTER_USER='copy2', -> MASTER_PASSWORD='123456', -> MASTER_LOG_FILE='mysql-bin.000005', -> MASTER_LOG_POS=216, -> MASTER_PORT=3308; Query OK, 0 rows affected, 2 warnings (0.05 sec)
mysql> START SLAVE; Query OK, 0 rows affected (0.03 sec)
mysql> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.186 Master_User: copy2 Master_Port: 3308 Connect_Retry: 60 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 548 Relay_Log_File: dominic-relay-bin.000002 Relay_Log_Pos: 615 Relay_Master_Log_File: mysql-bin.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 548 Relay_Log_Space: 790 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 1fb88a50-81b1-11e4-95e4-080027a9d0f9 Master_Info_File: /cifpay/mysqldb/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 1 row in set (0.00 sec)
--測試,OK!
--主主 -> 從: 按照主從一樣配置
五、配置參數說明
server-id
ID值唯一的標識了復制群集中的主從服務器,因此它們必須各不相同。master_id必須為1到232–1之間的一個正整數值,slave_id值必須為2到232–1之間的一個正整數值。
log-bin
表示打開binlog,打開該選項才可以通過I/O寫到Slave的relay-log,也是可以進行replication的前提;
binlog-do-db
表示需要記錄進制日志的數據庫。如果有多個數據庫可用逗號分隔,或者使用多個binlog-do-db選項
binlog-ignore-db
表示不需要記錄二進制日志的數據庫。如果有多個數據庫可用逗號分隔,或者使用多個binlog-do-db選項
replicate-do-db
表示需要同步的數據庫,如果有多個數據庫可用逗號分隔,或者使用多個replicate-do-db選項
replicate-ignore-db=mysql
表示不需要同步的數據庫,如果有多個數據庫可用逗號分隔,或者使用多個replicate-ignore-db=mysql選項
log-slave-updates
配置從庫上的更新操作是否寫入二進制文件,如果這台從庫,還要做其他從庫的主庫,那麼就需要打這個參數,以便從庫的從庫能夠進行日志同步
slave-skip-errors
在復制過程,由於各種原因導致binlog中的sql出錯,默認情況下,從庫會停止復制,要用戶介入。可以設置Slave-skip-errors來定義錯誤號,如果復制過程中遇到的錯誤號是定義的錯誤號,便可以跳過。如果從庫是用來做備份,設置這個參數會存在數據不一致,不要使用。如果是分擔主庫的查詢壓力,可以考慮。
sync_binlog=1 or N
sync_binlog的默認值是0,這種模式下,MySQL不會同步到磁盤中去。這樣的話,MySQL依賴操作系統來刷新二進制日志binary log,就像操作系統刷其他文件的機制一樣。因此如果操作系統或機器(不僅僅是MySQL服務器)崩潰,有可能binlog中最後的語句丟失了。要想防止這種情況,你可以使用sync_binlog全局變量,使binlog在每N次binlog寫入後與硬盤同步。當sync_binlog變量設置為1是最安全的,因為在crash崩潰的情況下,你的二進制日志binary log只有可能丟失最多一個語句或者一個事務。但是,這也是最慢的一種方式(除非磁盤有使用帶蓄電池後備電源的緩存cache,使得同步到磁盤的操作非常快)。
即使sync_binlog設置為1,出現崩潰時,也有可能表內容和binlog內容之間存在不一致性。如果使用InnoDB表,MySQL服務器處理COMMIT語句,它將整個事務寫入binlog並將事務提交到InnoDB中。如果在兩次操作之間出現崩潰,重啟時,事務被InnoDB回滾,但仍然存在binlog中。可以用–innodb-safe-binlog選項來增加InnoDB表內容和binlog之間的一致性。(注釋:在MySQL 5.1中不需要–innodb-safe-binlog;由於引入了XA事務支持,該選項作廢了),該選項可以提供更大程度的安全,使每個事務的 binlog(sync_binlog =1)和(默認情況為真)InnoDB日志與硬盤同步,該選項的效果是崩潰後重啟時,在滾回事務後,MySQL服務器從binlog剪切回滾的 InnoDB事務。這樣可以確保binlog反饋InnoDB表的確切數據等,並使從服務器保持與主服務器保持同步(不接收回滾的語句)。
auto_increment_offset和auto_increment_increment
auto_increment_increment和auto_increment_offset用於主-主服務器(master-to-master)復制,並可以用來控制AUTO_INCREMENT列的操作。兩個變量均可以設置為全局或局部變量,並且假定每個值都可以為1到65,535之間的整數值。將其中一個變量設置為0會使該變量為1。
這兩個變量影響AUTO_INCREMENT列的方式:auto_increment_increment控制列中的值的增量值,auto_increment_offset確定AUTO_INCREMENT列值的起點。
如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值被忽略。例如:表內已有一些數據,就會用現在已有的最大的自增值做為初始值。
六、二進制日志清除
主同步服務器產生的二進制日志會占據大量的磁盤空間,應定期刪除過期的bin-log。
A、通過PURGE MASTER LOGS刪除
如果您有一個在用的從屬服務器,該服務器當前正在讀取您正在試圖刪除的日志之一,則本語句不會起作用,而是會失敗,並伴隨一個錯誤。不過,如果從屬服務器是停止的,並且您碰巧清理了其想要讀取的日志之一,則從屬服務器啟動後不能復制。當從屬服務器正在復制時,本語句可以安全運行。您不需要停止它們。
要清理日志,需按照以下步驟:
1、在每個從屬服務器上,使用SHOW SLAVE STATUS來檢查它正在讀取哪個日志。
2、使用SHOW MASTER LOGS獲得主服務器上的一系列日志。
3、在所有的從屬服務器中判定最早的日志。這個是目標日志。如果所有的從屬服務器是更新的,這是清單上的最後一個日志。
4、制作您將要刪除的所有日志的備份。(建議備份)
5、清理所有的日志,但是不包括目標日志。
PURGE 語法
PURGE {MASTER | BINARY} LOGS TO ‘log_name’
PURGE {MASTER | BINARY} LOGS BEFORE ‘date’
用於刪除列於在指定的日志或日期之前的日志索引中的所有二進制日志。這些日志也會從記錄在日志索引文件中的清單中被刪除,這樣被給定的日志成為第一個。
BEFORE變量的date自變量可以為’YYYY-MM-DD hh:mm:ss’格式。MASTER和BINARY是同義詞。
例如:
?View Code BASH
1
2
3
4
5
6
7
8
9
#刪除binlog.000002之前的而不包含binlog.000002
mysql> PURGE MASTER LOGS TO 'binlog.000002';
#刪除2011-05-28 1:35:00之前的
mysql> PURGE MASTER LOGS BEFORE '2011-05-28 1:35:00';
#清除3天前的binlog
mysql> PURGE MASTER LOGS BEFORE DATE_SUB(NOW( ), INTERVAL 3 DAY);
B、設置expire-logs-days參數
缺省expire-logs-days為30天。這裡設為7天,可根據自己情況調整。
?View Code BASH
1
2
[mysqld]
expire-logs-days = 7
七、用於控制主、從服務器的SQL語句
A、用於控制主服務器的SQL語句
PURGE MASTER LOGS
用於刪除列於在指定的日志或日期之前的日志索引中的所有二進制日志。這些日志也會從記錄在日志索引文件中的清單中被刪除,這樣被給定的日志成為第一個。
RESET MASTER
可以刪除列於索引文件中的所有二進制日志,把二進制日志索引文件重新設置為空,並創建一個新的二進制日志文件。
SET SQL_LOG_BIN
如果客戶端使用一個有SUPER權限的賬戶連接,則可以禁用或啟用當前連接的二進制日志記錄。如果客戶端沒有此權限,則語句被拒絕,並伴隨有錯誤。
SHOW BINLOG EVENTS
用於在二進制日志中顯示事件。如果您不指定’log_name’,則顯示第一個二進制日志。
SHOW MASTER LOGS
用於列出服務器中的二進制日志文件。
SHOW MASTER STATUS
用於提供主服務器二進制日志文件的狀態信息。
SHOW SLAVE HOSTS
用於顯示當前使用主服務器注冊的復制從屬服務器的清單。
B、用於控制從服務器的SQL語句
CHANGE MASTER TO
可以更改從屬服務器用於與主服務器進行連接和通訊的參數。
LOAD DATA FROM MASTER
用於對主服務器進行快照,並拷貝到從屬服務器上。
LOAD TABLE tbl_name FROM MASTER
用於把表的拷貝從主服務器轉移到從屬服務器。
MASTER_POS_WAIT()
這實際上是一個函數,而不是一個語句。它被用於確認,從屬服務器已讀取並執行了到達主服務器二進制日志的給定位置。
RESET SLAVE
用於讓從屬服務器忘記其在主服務器的二進制日志中的復制位置。
SET GLOBAL SQL_SLAVE_SKIP_COUNTER
從主服務器中跳過後面的n個事件。要復原由語句導致的復制中止,這是有用的。
SHOW SLAVE STATUS
用於提供有關從屬服務器線程的關鍵參數的信息。
START SLAVE
用於啟動從屬服務器線程
STOP SLAVE
用於中止從屬服務器線程
以上內容摘自MySQL官方手冊,具體用法詳見:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#reset-master
八、主從復制如何提高可靠性
主從單向復制,從服務器只是實時的保存了主服務器的一個副本。當主服務器發生故障時,可以切換到從服務器繼續做查詢,但不能更新。
如果采用雙向復制,即兩台mysql服務器即作為主服務器,又作為從服務器。那麼兩者都可以執行更新操作並能實現負載均衡,當一方出現故障時,另一方不受影響。但是,除非能保證任何更新操作順序都是安全的,否則雙向復制會導致失敗。