Mysql 實現基於binlog的主從同步


 

 

工作原理

1、主節點必須啟用二進制日志,記錄任何修改了數據庫數據的事件。
2、從節點開啟一個線程(I/O Thread)把自己扮演成 mysql 的客戶端,通過 mysql 協議,請求主節點的二進制日志文件中的事件
3、主節點啟動一個線程(dump Thread),檢查自己二進制日志中的事件,跟對方請求的位置對比,如果不帶請求位置參數,則主節點就會從第一個日志文件中的第一個事件一個一個發送給從節點。
4、從節點接收到主節點發送過來的數據把它放置到中繼日志(Relay log)文件中。並記錄該次請求到主節點的具體哪一個二進制日志文件內部的哪一個位置(主節點中的二進制文件會有多個,在后面詳細講解)。
5、從節點啟動另外一個線程(sql Thread ),把 Relay log 中的事件讀取出來,並在本地再執行一次

 

配置mysql主從同步

准備兩台測試的虛擬機,如上安裝mysql環境,並開啟mysql服務

主master : 192.168.8.10

從slave  :   192.168.8.11

1、配置主庫:

1)、授權給從數據庫服務器

mysql> GRANT REPLICATION SLAVE ON *.* to 'rep1'@'192.168.8.11' identified by 'test123456';
mysql> FLUSH PRIVILEGES; 

2)、修改主庫配置文件,開啟binlog,並設置server-id,每次修改配置文件后都要重啟mysql服務才會生效

vim /etc/my.cnf

在該配置文件[mysqld]下面添加下面內容:

[mysqld] log-bin=/var/lib/mysql/binlog server-id=1 binlog-do-db = cmdb datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock ......

server-id:master端的ID號【必須是唯一的】;

log-bin:同步的日志路徑及文件名,一定注意這個目錄要是mysql有權限寫入的(我這里是偷懶了,直接放在了下面那個datadir下面);

binlog-do-db:要同步的數據庫名

還可以顯式設置不同步的數據庫:

binlog-ignore-db = mysql 不同步mysql庫和test庫
binlog-ignore-db = test

 

修改配置文件后,重啟服務:service mysqld restart

如果啟動失敗,通過cat /var/log/mysqld.log | tail -30  查看mysql啟動失敗的日志,從日志內容尋找解決方案

3)、查看主服務器當前二進制日志名和偏移量,這個操作的目的是為了在從數據庫啟動后,從這個點開始進行數據的恢復

+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| binlog.000001 |     1304 | cmdb         |                  |
+---------------+----------+--------------+------------------+
1 row in set (0.00 sec)

主服務器已配置好。

 

2、配置從庫

1)、理所當然也是從配置文件着手,在/etc/my.cnf 添加下面配置:

[mysqld] server-id=2 master-host=192.168.8.10 master-user=rep1 master-password=test123456 master-port=3306 replicate-do-db=cmdb ......

# 開啟中繼日志
relay-log=relay-log
relay-log-index=relay-log.index
server-id=2
innodb_file_per_table=ON
skip_name_resolve=ON

重啟時報錯:mysqld: unknown variable ‘master-host=

說明mysql不認識這些變量,網上搜羅了一番,原因是mysql5.5+版本主從復制不支持這些變量,需要在從庫上用命令來設置:

mysql> CHANGE MASTER TO MASTER_HOST='192.168.8.10',   MASTER_PORT=3306,   MASTER_USER='rep1',   MASTER_PASSWORD='test123456',   MASTER_LOG_FILE='binlog.000001',   MASTER_LOG_POS=1304; #后面兩個參數的值與主庫保持一致

PS: 最好在從服務器的my.cnf里設置read_only選項,防止發生意外(連接用戶[rep1]不能有SUPER權限,否則無效)

2)、啟動slave進程

mysql> slave start; Query OK, 0 rows affected (0.04 sec)

3)、查看slave的狀態,如果下面兩項值為YES,則表示配置正確:

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

從庫正在等待主庫更新數據。。。Waitin for master to send event...

 

三、同步主庫已有數據到從庫

進行第一次同步之前,先手動同步一下主從服務器

主庫操作:

1、停止主庫的數據更新操作

mysql> flush tables with read lock;

2、新開終端,生成主數據庫的備份(導出數據庫)

[root@zhoujietest ~]# mysqldump -uroot -ptest123 cmdb > cmdb.sql

3、將備份文件傳到從庫

[root@zhoujietest ~]# scp cmdb.sql root@192.168.8.11:/root/

4、主庫解鎖

mysql> unlock tables; 

從庫操作:

1、停止從庫slave

mysql> slave stop;

2、新建數據庫cmdb

mysql> create database cmdb default charset utf8;

3、導入數據

[root@ops-dev ~]# mysql -uroot -ptest123 cmdb<cmdb.sql 

4、查看從庫已有該數據庫和數據 

mysql> show databases; +--------------------+
| Database           |
+--------------------+
| information_schema |
| cmdb               |
| mysql              |
| performance_schema |
| test               |
+--------------------+

 5、再次啟動slave,啟動的時候,記得加上skip-slave-start選項,使之不會立刻去連接master 

mysql> slave start --skip-slave-start;
[or]
mysql> start slave (可以指定線程類型:IO_THREAD ,SQL_THREAD, 如果不指定,則兩個都啟動。)

 

此時主從庫的數據完全一致,如果對主庫進行增刪改操作,從庫會自動同步進行操作。 

Reference links:

https://www.cnblogs.com/zhoujie/p/mysql1.html

https://www.cnblogs.com/itfenqing/p/4429436.html (次要)

https://blog.csdn.net/z69183787/article/details/70183284

http://blog.sina.com.cn/s/blog_747f4c1d0102w9pp.html (binlog-do-db配置慎用)

 

實踐出真章:

從理想角度看,主從數據庫應該無故障的運轉下去,可以有時候還是會出現一些莫名其妙的問題,比如說即便從未在從服務器上手動更新過數據,但還是可能遇到“Error: 1062 Duplicate entry”錯誤,具體原因不詳,可能是MySQL本身的問題。

遇到這類問題的時候,從服務器會停止復制操作,我們只能手動解決問題,具體的操作步驟如下:

mysql> set global sql_slave_skip_counter = 1;
mysql> start slave;

同樣的操作可能需要進行多次,也可以設置自動處理此類操作,在從服務器的my.cnf里設置:

slave-skip-errors=1062

最后再嘮叨一下日志的問題:時間長了,數據庫服務器上的二進制文件會越來越多,清理是必要的,你可以設置自動清理,相關參數是expire_logs_days

也可以使用手動刪除的方式,但這里說的手動不是指rm,而是指PURGE BINARY LOGS,刪除任何日志前,最好在所有的從服務器上通過show slave status命令確認一下相關日志是否已經無用。

更詳細的介紹參考官方文檔:How to Set Up Replication,不喜歡英文的話可以看老葉同志的中文翻譯

補充:[ERROR] Error in Log_event::read_log_event(): 'Event too big'

在使用主從復制的時候,出現的問題多半是和日志(主服務器的二進制日志,從服務器的延遲日志)相關的。比如說加入你遇到了上面的錯誤,你可以根據錯誤日志的信息在主從數據庫服務器上分別執行:

mysqlbinlog 日志文件 > /dev/null

查看錯誤,如果沒有錯誤,則不會有任何輸出,反之會輸出錯誤信息,如果確定了錯誤是出現在主服務器二進制日志上,可以跳過適當的位置,再在從服務器上重新設定LOG_POS,如果確定了錯誤是出現在從服務器延遲日志上,則可以刪除從服務器的延遲日志(使用CHANGE TO MASTER的時候,除非設定了延遲日志信息,否則會自動刪除延遲日志),並在從服務器上重新設定LOG_POS。期間也可以考慮手動執行不能自動執行的SQL日志。

補充:配置的時候如果版本允許最好打開sync_binlog選項。

補充:有時候,從服務器延遲日志可能已經損壞,這時需要執行CHANGE MASTER TO設置新的日志文件信息,但是在從服務器上SHOW SLAVE STATUS會顯示很多日志信息,他們的含義有所不同:

Master_Log_File:Read_Master_Log_Pos 是IO相關的日志信息
Relay_Master_Log_File:Exec_Master_Log_Pos 是SQL相關的日志信息

從服務器需要設置的是SQL相關的日志信息:

slave stop;
change master to master_log_file=’(binlog name in relay_master_log_file)’, master_log_pos=(exec_master_log_pos number);
slave start;

1) When you are using the master as a consistent snapshot, use SHOW MASTER STATUS to determine the position.
2) When you are using a slave as a consistent snapshot, use SHOW SLAVE STATUS and Exec_Master_Log_Pos.

參考鏈接

補充:缺省情況下,從服務器會以主機名命名延遲日志,所以一旦你修改了從服務器的主機名就會造成問題,新版MySQL會提示你這個情況:

[Warning] Neither --relay-log nor --relay-log-index were used;
so replication may break when this MySQL server acts as a slave and has his hostname changed!!
Please use '--relay-log=name-relay-bin' to avoid this problem.

補充:主庫 binlog-do-db 配置,建議在沒有完全測試清楚的情況下,mysql復制的幾個選擇性參數要慎用,因為在binlog_format [STATEMENT, ROW, MIXED]不同的情況下,會對binlog產生不同的影響,從而可能導致主從數據不一致。
如果有需要,可以使用replicate-wild-do-table和replicate-ignore-table代替。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM