MySQL主從模式及配置
主伺服器:192.168.20.239
從伺服器:192.168.20.176
主從原理
主節點
1、當主節點上進行 insert、update、delete 操作時,會按照時間先後順序寫入到 binlog 中;
2、當從節點連線到主節點時,主節點會建立一個叫做 binlog dump 的執行緒;
3、一個主節點有多少個從節點,就會建立多少個 binlog dump 執行緒;
4、當主節點的 binlog 發生變化的時候,也就是進行了更改操作,binlog dump 執行緒就會通知從節點 (Push模式),並將相應的 binlog 內容傳送給從節點;
從節點
當開啟主從同步的時候,從節點會建立兩個執行緒用來完成資料同步的工作。
I/O執行緒: 此執行緒連線到主節點,主節點上的 binlog dump 執行緒會將 binlog 的內容傳送給此執行緒。此執行緒接收到 binlog 內容後,再將內容寫入到本地的 relay log。
SQL執行緒: 該執行緒讀取 I/O 執行緒寫入的 relay log,並且根據 relay log 的內容對從資料庫做對應的操作。
主從配置一般都是和讀寫分離相結合,主伺服器負責寫資料,從伺服器負責讀資料,並保證主伺服器的資料及時同步到從伺服器。
一、配置主伺服器:
1:在mysql下找到my.ini檔案,一般在 C:\ProgramData\MySQL\MySQL Server 5.7
在其[mysqld] 下新增主伺服器端配置:
#伺服器 id
server-id=1
#二進位制檔案存放路徑
log-bin=C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql-bin
#待同步的資料庫 (如果這一行沒有,那麼就是針對所有的不用忽略的資料庫進行同步)
#binlog-do-db=test_db
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=information_schema
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=mysql
注意,上面的mysql-bin 並不是指一個資料夾,而是指 存放為二進位制資料
2:儲存my.ini檔案,重啟資料庫,然後會在C:\ProgramData\MySQL\MySQL Server 5.7\Data 下看到 mysql-bin.index 檔案和 mysql-bin.000001 檔案;
3:連線主資料庫
mysql -u root -p123456
4:給要連線的從伺服器設定許可權:(注意下面的 單引號 分號 )
grant replication slave,reload,super on *.* to 'backup'@'192.168.20.%' identified by '123456';
註釋: 給主機192.168.20.%新增許可權,使用者名稱:backup,密碼:123456;(只需輸入一次就可以了)
*.* 表示任意資料庫中的任意表,'192.168.20.%' 表示只允許192.168.20.··網段的“從”訪問“主” 的資料庫
如果你把字元,單引號或者是分號漏掉了,那麼執行會沒有反應的,如果執行成功,會顯示 query ok
mysql> use mysql; mysql> select user from user; +---------------+ | user | +---------------+ | test | | backup | | mysql.session | | mysql.sys | | root | +---------------+
#檢視使用者發現多了backup
實際就是在mysql中新增一個backup的 slave 賬號,並授權給從伺服器。建立backup使用者,並授權給192.168.20.··使用。
5:輸入命令 show master status; # 找到File 和 Position 的值記錄下來; (如果你不小心把主伺服器上的資料庫刪除了,然後重新添加了一個同名的,但是這裡的position 是會改變的,一定要注意)
6: 匯出主資料庫的資料
mysqldump -u root -p123456 --databases test_db > test_db.mysql
7:把匯出的sql語句,匯入從資料庫
方法一:
mysql>source F:\dir\test_db.mysql
方法二:
先建立DB,然後:mysql -uroot -p123456 test_db < test_db.mysql
這樣從伺服器上也有了 test_db 這個資料庫了
二、配置從伺服器:
1:在mysql下找到my.ini檔案,在其[mysqld] 下新增從伺服器端配置:
#伺服器 id ,不能和主伺服器一致
server-id=2
#同步的資料庫(需要備份的資料庫名),不寫本行 表示 同步所有資料庫
#replicate-do-db=test_db
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=information_schema
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=mysql
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=test
2:儲存my.ini檔案,重啟從資料庫,在mysql5.1以上版本中是不支援1中master設定的,如果添加了master設定,資料庫就無法重啟了(這個可能是針對以前的低於5.1的資料庫的,反正我們沒有用到那麼低的,所以不用管什麼 master設定);
3:用上面分配的賬號backup,嘗試連線主資料庫,成功
mysql -ubackup -p123456 -h192.168.20.239
4:重新開啟一個dos介面,用管理員賬號連線從資料庫
mysql –uroot –p123456
修改對主資料庫的連線的引數:
mysql> change master to master_host='192.168.20.239',master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=154;
ps:可能會報一個錯誤,大概的意思是說slave執行緒正在執行,不能設定,這樣的話,執行mysql> stop slave; 停止slave執行緒,然後再設定連線的引數;
設定後,可以執行命令檢視狀態,Master_User: backup 就是剛剛的賬號
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.20.239 Master_User: backup Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 154 Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000019 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: No 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: 1258 Relay_Log_Space: 308 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: 1236 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file' Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: a2085118-c063-11ec-a4a8-00090faa0001 Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: 220508 16:56:41 Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
注意:上面的IO執行緒啟動失敗了
Slave_IO_Running: No
錯誤資訊 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
原因:一方面是因為網路通訊的問題,也有可能是日誌讀取錯誤的問題。因為我是重新設定的,所以可能是讀取順序的錯誤。
解決辦法:
在 slave 執行 mysql> stop slave 在 master 執行 mysql> show master status; 重新整理日誌:mysql> flush logs; 因為重新整理日誌file的位置會+1,即File變成為:mysqld-bin.000002 馬上到 slave 執行 mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysqld-bin.000002',MASTER_LOG_POS=154; mysql> slave start;
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.20.239 Master_User: backup Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 154 Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes ******************************************************
Slave_IO_Running: Yes 這個表示:連線到主庫,並讀取主庫的日誌到本地,生成本地日誌檔案. yes表示 網路正常
Slave_SQL_Running: Yes 這個表示:讀取本地日誌檔案,並執行日誌裡的SQL命令。 yes表示 表結構正常
5:在 master 中新增一行資料,發現 slave 中也自動增加了,並且Position保持一致。
6:使用 show processlist
語句可檢視執行緒狀態
主資料庫上:可以看到第一個執行緒的 State 是 「Master has sent all binlog to slave; waiting for more updates」,說明同步執行緒一直在執行中。
mysql> show processlist; +----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+ | 2 | root | localhost:11714 | test_db | Query | 0 | starting | show processlist | | 5 | backup | DESKTOP-P02RV6K:50511 | NULL | Binlog Dump | 2315 | Master has sent all binlog to slave; waiting for more updates | NULL | +----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+
從資料庫上:
mysql> show processlist; +----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+ | 6 | root | localhost:58744 | test_db | Query | 0 | starting | show processlist | | 9 | system user | | NULL | Connect | 2230 | Waiting for master to send event | NULL | | 10 | system user | | NULL | Connect | 858 | Slave has read all relay log; waiting for more updates | NULL | +----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+
三、可能出問題的地方
1:開始一定要把資料庫資料同步,保證資料一致性。
2:如果Slave_IO_Running: NO 那麼要看看是不是 (1) A有賬戶在用dos介面在登陸資料庫而沒有退出 (2) A資料庫的postion和file有改變,而B裡面change的時候,還是用的以前的資料?
3:主庫不小心宕機,重啟之後發現主庫資料更新,但是從庫不執行,造成了主從的資料不同步。但是在從上面檢視 Slave_IO_Running 和 從庫的狀態,都是正常的。這個時候要注意在主庫看看 show master status 看看postion和file是不是和從庫一致的,我就發現我的主庫宕機之後再次開機就不一樣了。這個時候在從庫執行
CHANGE MASTER TO MASTER_HOST='192.168.20.239',MASTER_USER='backup',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=154
但是這裡還是有個問題,雖然這個時候,主從可以開始同步了,但是由於這中間,如果不是及時發現,那麼主從的資料還是會有差異的,那這個怎麼解決呢? 答案是,只能重新設定主從。
4:如果我在主裡面 delete from xx表 那麼在從裡面,到底是讀出主裡面刪除了哪些行,進而對從進行刪除?還是直接也是和主一樣,運行了 delete from xx呢?答案是後者,從會像主一樣,直接執行 delete from xx 。所以如果你是有上面3這個問題發生(主從資料不同步了),後面再進行了其他操作的話,會越來越不同步的,所以趕緊重新做主從
5:從庫掛了怎麼辦
在主服務的 binlog dump 執行緒將指定的 binlog 資訊發給從服務時,除了日誌內容,還包括本次傳送內容在主服務端的 bin-log 日誌檔名稱以及位置資訊。
從服務的 I/O 執行緒接收到資訊後將日誌內容寫入realy-log 檔案(mysql-relay-bin.xxxxxx)的末端,並將讀取到的主服務端的 bin-log 的檔名和位置記錄到 master-info 中(通過 show slave status
中的 Master_Info_File
欄位可以看到 master.info 儲存的位置),以便下一次讀取時能告訴主服務從哪裡開始同步。
從服務的 SQL 執行緒檢測到 realy-log 新增了內容後,解析日誌檔案生成對應的 sql 語句,並應用這些 sql 到資料庫,保證主從資料一致性。
所以,即使從庫掛掉了,因為有 master.info 記錄了上一次同步的位置,只要同步服務再次啟動,那就可以從上次同步的位置繼續增量同步了。
參考資料
1:公眾號[古時的風箏]MySQL主從配置和讀寫分離 https://www.cnblogs.com/fengzheng/p/13401783.html
2:windows 下mysql 主從庫的配置 https://www.cnblogs.com/joeylee/archive/2013/01/24/2875515.html