當前位置:首頁 » 數據倉庫 » 資料庫主從不同步
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

資料庫主從不同步

發布時間: 2023-01-31 15:16:15

資料庫讀寫分離如何保證主從一致性

當我們的資料庫壓力主鍵變大的時候,我們會嘗試增加一些從節點來分攤主節點的查詢壓力。而一般來說,我們是用一主多從的結構來作為讀寫分離的基本結構。

而一般來說我們有兩種常用的方法來實現讀且分離架構:

客戶端直接分離

這種方式是由客戶端,或者我們的微服務直接進行資料庫的讀寫選擇。將讀庫選擇路由到主庫上進行,將查詢路由到從主庫上進行。

這種方式的優點在於因為是直連所以性能比較高,但是需要由業務團隊了解資料庫的實例細節,當資料庫做調整的時候就需要業務側同步改造。

使用數據中間件代理

這種方式是由一層代理層對數據的讀寫做分發,業務層將所有的請求都通過代理來實現。

這種方式的優點在於對於業務層不需要感知到資料庫的存在,但問題在於數據中間件的性能要求較高,還需要專人來進行優化和維護,整體架構較為復雜。

但是我們發現,盡管這兩種方式各有優劣。但核心都是通過數據的寫入、查詢請求的路由而實現的,那麼這就會引發標題的問題:

主備同步存在延遲,所以在延遲時間內對插入的內容進行查詢則無法查詢到最新提交的事務。

那麼如何保證主從一致性的問題,其實就變成了如何處理主從延遲的問題。

根據項目的大小,團隊的規模以及主機的部署模式。我們處理問題的方法也有很多種。

最簡單強硬的就是強制讀主庫。

一般情況下我們在不同的查詢中會有不同程度的一致性要求。我們可以將需要保證數據一致性的請求配置強制查詢主庫,而對於無強依賴的查詢請求仍然查詢備庫。

盡管這個方案不是很優雅,但是是最簡單實現的方法,並且在Spring等框架的支持下一般只需要加一個註解就能實現。但這個方法的問題也是顯而易見的,如果存在大量的強一致性要求的查詢語句,則相當於沒有進行讀寫分離與擴展。那麼這種方法就會導致系統在資料庫層面沒有有效的擴展手段了。

由於問題產生的來源是主從延遲,所以在下一次查詢的時候進行一段時間的等待以彌補這種延遲即可。

所以在進行主庫的數據插入之後,讓資料庫數據連接或者對應的執行線程等待一段時間後返回。通過等待時間來消化掉主從備份的延遲時間。但是這個方法也有一些問題比如:這個等待時間一般是固定的,即便主從已經無延遲了也會繼續等待到時間結束;如果在服務高峰時期,有可能數據在等待時間結束後仍然沒有完成同步則仍然會存在一致性問題。

但這種方法優雅的地方是可以配合業務來進行實現,舉例來說當用戶下單之後,通過下單送卷或者下單抽獎的方式從前端拖住用戶,從而當用戶在一次連續操作中再次查詢自己訂單的時候中間必然會間隔一定時間,也就讓需要再次查詢數據的時候保證了數據的一致性。

上述兩種方案看起來可能不那麼「技術」,感覺有點投機取巧。那麼下面咱們可以分兩種情況來討論用更高技術的方法如何實現一致性。

對於主從復制來說,是當主庫完成一個事務後,通知給從庫,當從庫接受到後,則主庫完成返回客戶端。所以當主庫完成事務後,僅能確保從庫已經接受到了,但是不能保證從庫執行完成,也就是導致了主從備份延遲。

但是從庫執行數據是有進度的,而這個進度是可以通過show slave status語句中的seconds_behind_master來進行描述,這個參數描述從庫落後了主庫數據多少秒,當這個參數為0時,我們可以認為從庫和主庫已經基本上沒有延遲了,那麼這時候就可以查詢請求。

但seconds_behind_master是秒級的,所以只能大概地判斷,由於精度較低,所以還是可能出現不一致的情況。

如果要求精準執行的話,我們可以比較同步文件的執行記錄,具體來說是:

所以當Relay_Master_Log_File和Exec_Master_Log_Pos和其一致的時候,就說明從庫的已執行數據已經追上主庫了,那麼這時就可以說保證了主從一致性了

但是比較同步文件的執行記錄方法的問題在於,如果當前的這個事務的binlog尚未傳入到從庫,即Master_Log_File和Read_Master_Log_Pos未更新,也就無法保證從庫已經包含最新的主庫事務了。

而為了保證在一主一備的情況下,從庫里一定接受到數據了,也就是Master_Log_File和Read_Master_Log_Pos中的數據是和主庫一致的,我們可以開啟semi-sync replication半同步復制。

半同步復制的原理是在主庫提交事務前先將binlog發送給從庫,然後當從庫接受後返回一個應答,主庫只有在接受到這個應答之後才返回事務執行完成。這樣就可以保證從庫的Master_Log_File和Read_Master_Log_Pos與主庫是一致的,從而解決了主從一致的問題。

半同步復制可以解決一主一備的情況,但是當一主多備的時候,只要主庫接受到一個從庫的應答,就會返回事務執行完成。而這時當請求打到未完成同步的從庫上時就會發生主從延遲。

所以針對一主多備的情況,我們可以將目光集中在執行查詢的從庫上,即確保 我們即將查詢的備庫已經執行了我們預期的事務。 那麼我們的問題就變成兩部分:1. 確認主庫事務,2. 查詢數據條件。

確認主庫事務

當我們提交完一個事務後,可以通過執行show master status來得到主庫中的數據事務文件(File)和位置記錄(Position)。

查詢數據條件

當我們要查詢從庫數據的時候,我們可以通過語句select master_pos_wait(File, Position, 1);來查詢當前是否已經執行到了該記錄(當返回值>=0的時候說明已經執行過了)。其中最後的數字1表示阻塞時長。

通過先確認主庫事務記錄,再判確認備庫是否已經執行了了主庫對應的事務。

但是可以發現,這種方法要求查詢的時候知道主庫的事務信息,對場景有很大的限制。

主從一致的問題源自主從延遲,所以我們就是從如何消除延遲來解決問題。簡單點的方案我們可以不走備庫、或者直接等待一段時間來忽略延遲的影響。在一主一備的情況下我們可以粗力度的用seconds_behind_master來判斷或者用Relay_Master_Log_File和Exec_Master_Log_Pos來判斷。而當一主多從的情況下我們則需要在查詢前傳入主庫執行的事務記錄才能保證數據一致性。

可以看出,當數據規模和部署方式變更的時候,好的解決方案將會越來越多。我認為根據實際業務情況選擇最合適的方法才是最重要的。



⑵ mysql主從資料庫不同步的2種解決方法

今天發現Mysql的主從資料庫沒有同步
先上Master庫:
mysql>show
processlist;
查看下進程是否Sleep太多。發現很正常。
show
master
status;
也正常。
mysql>
show
master
status;
+-------------------+----------+--------------+-------------------------------+
|
File
|
Position
|
Binlog_Do_DB
|
Binlog_Ignore_DB
|
+-------------------+----------+--------------+-------------------------------+
|
mysqld-bin.000001
|
3260
|
|
mysql,test,information_schema
|
+-------------------+----------+--------------+-------------------------------+
1
row
in
set
(0.00
sec)
再到Slave上查看
mysql>
show
slave
status\G
Slave_IO_Running:
Yes
Slave_SQL_Running:
No
可見是Slave不同步
下面介紹兩種解決方法:
方法一:忽略錯誤後,繼續同步
該方法適用於主從庫數據相差不大,或者要求數據可以不完全統一的情況,數據要求不嚴格的情況
解決:
stop
slave;
#表示跳過一步錯誤,後面的數字可變
set
global
sql_slave_skip_counter
=1;
start
slave;
之後再用mysql>
show
slave
status\G
查看:
Slave_IO_Running:
Yes
Slave_SQL_Running:
Yes
ok,現在主從同步狀態正常了。。。
方式二:重新做主從,完全同步
該方法適用於主從庫數據相差較大,或者要求數據完全統一的情況
解決步驟如下:
1.先進入主庫,進行鎖表,防止數據寫入
使用命令:
mysql>
flush
tables
with
read
lock;
注意:該處是鎖定為只讀狀態,語句不區分大小寫
2.進行數據備份
#把數據備份到mysql.bak.sql文件
[root@server01
mysql]#mysqlmp
-uroot
-p
-hlocalhost
>
mysql.bak.sql
這里注意一點:資料庫備份一定要定期進行,可以用shell腳本或者python腳本,都比較方便,確保數據萬無一失
3.查看master
狀態
mysql>
show
master
status;
+-------------------+----------+--------------+-------------------------------+
|
File
|
Position
|
Binlog_Do_DB
|
Binlog_Ignore_DB
|
+-------------------+----------+--------------+-------------------------------+
|
mysqld-bin.000001
|
3260
|
|
mysql,test,information_schema
|
+-------------------+----------+--------------+-------------------------------+
1
row
in
set
(0.00
sec)
4.把mysql備份文件傳到從庫機器,進行數據恢復
#使用scp命令
[root@server01
mysql]#
scp
mysql.bak.sql
[email protected]:/tmp/
5.停止從庫的狀態
mysql>
stop
slave;
6.然後到從庫執行mysql命令,導入數據備份
mysql>
source
/tmp/mysql.bak.sql
7.設置從庫同步,注意該處的同步點,就是主庫show
master
status信息里的|
File|
Position兩項
change
master
to
master_host
=
'192.168.128.100',
master_user
=
'rsync',
master_port=3306,
master_password='',
master_log_file
=
'mysqld-bin.000001',
master_log_pos=3260;
8.重新開啟從同步
mysql>
stop
slave;
9.查看同步狀態
mysql>
show
slave
status\G
查看:
Slave_IO_Running:
Yes
Slave_SQL_Running:
Yes
好了,同步完成啦。

⑶ 資料庫主從不一致,怎麼解

由於各種原因,mysql主從架構經常會出現數據不一致的情況出現,大致歸結為如下幾類
1:備庫寫數據
2:執行non-deterministic query
3:回滾摻雜事務表和非事務表的事務
4:binlog或者relay log數據損壞
數據不同步給應用帶來的危害是致命的,當出現主從數據不一致的情況,常見的應對方法是先把從庫下線,然後找個半夜三更的時間把應用停掉,重新執行同步,如果資料庫的體積十分龐大,那工作量可想而知,會讓人崩潰。本文介紹使用percona-toolkit工具對mysql主從資料庫的同步狀態進行檢查和重新同步。
一:安裝percona-toolkit

二:修改mysql 的binlog格式binlog_format參數為row格式
mysql binlog日誌有三種格式,分別為Statement, Mixed,以及ROW!
1.Statement:
每一條會修改數據的sql都會記錄在binlog中。
優點:不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高性能。(相比row能節約多少性能與日誌量,這個取決於應用的SQL情況,正常同一條記錄修改或者插入row格式所產生的日誌量還小於Statement產生的日誌量,但是考慮到如果帶條件的update操作,以及整表刪除,alter表等操作,ROW格式會產生大量日誌,因此在考慮是否使用ROW格式日誌時應該跟據應用的實際情況,其所產生的日誌量會增加多少,以及帶來的IO性能問題。)
缺點:由於記錄的只是執行語句,為了這些語句能在slave上正確運行,因此還必須記錄每條語句在執行的時候的一些相關信息,以保證所有語句能在slave得到和在master端執行時候相同 的結果。另外mysql 的復制,像一些特定函數功能,slave可與master上要保持一致會有很多相關問題(如sleep()函數, last_insert_id(),以及user-defined functions(udf)會出現問題).
2.Row
不記錄sql語句上下文相關信息,僅保存哪條記錄被修改。
優點: binlog中可以不記錄執行的sql語句的上下文相關的信息,僅需要記錄那一條記錄被修改成什麼了。所以rowlevel的日誌內容會非常清楚的記錄下每一行數據修改的細節。而且不會出現某些特定情況下的存儲過程,或function,以及trigger的調用和觸發無法被正確復制的問題
缺點:所有的執行的語句當記錄到日誌中的時候,都將以每行記錄的修改來記錄,這樣可能會產生大量的日誌內容,比如一條update語句,修改多條記錄,則binlog中每一條修改都會有記錄,這樣造成binlog日誌量會很大,特別是當執行alter table之類的語句的時候,由於表結構修改,每條記錄都發生改變,那麼該表每一條記錄都會記錄到日誌中。
3.Mixed
是以上兩種level的混合使用,一般的語句修改使用statment格式保存binlog,如一些函數,statement無法完成主從復制的操作,則採用row格式保存binlog,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式,也就是在Statement和Row之間選擇一種.新版本的MySQL中隊row level模式也被做了優化,並不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄。至於update或者delete等修改數據的語句,還是會記錄所有行的變更。

⑷ 哪些原因會導致mysql主從數據不一致

1. 在有主鍵或者唯一鍵的情況下,Slave 重放 Binlog 並不會去比較檢索到的記錄的每一列是否和BI相同,因此如果 Slave 和 Master 存在數據不一致,會直接覆蓋 Slave 的數據而不會報錯。
2. 在沒有主鍵或者唯一鍵的情況下,Hash Scan / Hash Scan Over Index 的執行效率 在理論上分析高於 Table Scan 和Index Scan 。
3. 在沒有主鍵或者唯一鍵的情況下,Slave 選擇的二級索引是第一個所有的列都在 BI 中存在的索引,不一定是 Master 執行計劃所選擇的索引。