架構師之路 12 多庫多事務降低資料不一致概率

2021-09-11 06:07:44 字數 3529 閱讀 6092

我們經常使用事務來保證資料庫層面資料的acid特性。

舉個栗子,使用者下了乙個訂單,需要修改餘額表,訂單表,流水表,於是會有類似的偽**:

start transaction;

curdtable t_account; any exception rollback;

curdtable t_order; any exception rollback;

curdtable t_flow; any exception rollback;

commit;

如果對餘額表,訂單表,流水表的sql操作全部成功,則全部提交,如果任何乙個出現問題,則全部回滾,以保證資料的一致性。

網際網路的業務特點,資料量較大,併發量較大,經常使用拆庫的方式提公升系統的效能。如果進行了拆庫,餘額、訂單、流水可能分布在不同的資料庫上,甚至不同的資料庫例項上,此時就不能用事務來保證資料的一致性了。這種情況下如何保證資料的一致性,是今天要討論的話題。

補償事務是一種在業務端實施業務逆向操作事務,來保證業務資料一致性的方式。

舉個栗子,修改餘額表事務為

int do_accountt(uid, money)
那麼補償事務可以是:

int compensate_accountt(uid, money)
同理,訂單表操作為

do_ordert,新增乙個訂單

compensate_ordert,刪除乙個訂單

要保重餘額與訂單的一致性,可能要寫這樣的**:

// 執行第乙個事務

int flag = do_accountt();

if(flag = yes)else

}

該方案的不足是:

(1)不同的業務要寫不同的補償事務,不具備通用性

(2)沒有考慮補償事務的失敗

(3)如果業務流程很複雜,if/else會巢狀非常多層

例如,如果上面的例子加上流水表的修改,加上do_flowt和compensate_flowt,可能會變成乙個這樣的if/else:

// 執行第乙個事務

int flag = do_accountt();

if(flag=yes)

}else

}else

單庫是用這樣乙個大事務保證一致性:

start transaction;

curdtable t_account; any exception rollback;

curdtable t_order; any exception rollback;

curdtable t_flow; any exception rollback;

commit;

拆分成了多個庫,大事務會變成三個小事務:

start transaction1;

//第乙個庫事務執行

curdtable t_account; any exception rollback;

…// 第乙個庫事務提交

commit1;

start transaction2;

//第二個庫事務執行

curdtable t_order; any exception rollback;

…// 第二個庫事務提交

commit2;

start transaction3;

//第三個庫事務執行

curdtable t_flow; any exception rollback;

…// 第三個庫事務提交

commit3;

乙個事務,分成執行與提交兩個階段,執行的時間其實是很長的,而commit的執行其實是很快的,於是整個執行過程的時間軸如下:

第乙個事務執行200ms,提交1ms;

第二個事務執行120ms,提交1ms;

第三個事務執行80ms,提交1ms;

那在什麼時候系統出現問題,會出現不一致呢?

回答:第乙個事務成功提交之後,最後乙個事務成功提交之前,如果出現問題(例如伺服器重啟,資料庫異常等),都可能導致資料不一致。

如果改變事務執行與提交的時序,變成事務先執行,最後一起提交,情況會變成什麼樣呢:

第乙個事務執行200ms;

第二個事務執行120ms;

第三個事務執行80ms;

第乙個事務執行1ms;

第二個事務執行1ms;

第三個事務執行1ms;

那在什麼時候系統出現問題,會出現不一致呢?

問題的答案與之前相同:第乙個事務成功提交之後,最後乙個事務成功提交之前,如果出現問題(例如伺服器重啟,資料庫異常等),都可能導致資料不一致。

這個變化的意義是什麼呢?

方案一總執行時間是303ms,最後202ms內出現異常都可能導致不一致;

方案二總執行時間也是303ms,但最後2ms內出現異常才會導致不一致;

雖然沒有徹底解決資料的一致性問題,但不一致出現的概率大大降低了!

事務提交後置降低了資料不一致的出現概率,會帶來什麼***呢?

回答:事務提交時會釋放資料庫的連線,第一種方案,第乙個庫事務提交,資料庫連線就釋放了,後置事務提交的方案,所有庫的連線,要等到所有事務執行完才釋放。這就意味著,資料庫連線占用的時間增長了,系統整體的吞吐量降低了。

trx1.exec();

trx1.commit();

trx2.exec();

trx2.commit();

trx3.exec();

trx3.commit();

優化為:

trx1.exec();

trx2.exec();

trx3.exec();

trx1.commit();

trx2.commit();

trx3.commit();

這個小小的改動(改動成本極低),不能徹底解決多庫分布式事務資料一致性問題,但能大大降低資料不一致的概率,帶來的***是資料庫連線占用時間會增長,吞吐量會降低。對於一致性與吞吐量的折衷,還需要業務架構師謹慎權衡折衷。

多庫多事務降低資料不一致概率

我們經常使用事務來保證資料庫層面資料的acid特性。舉個栗子,使用者下了乙個訂單,需要修改餘額表,訂單表,流水表,於是會有類似的偽 start transaction curdtable t account any exception rollback curdtable t order any e...

架構師之路 快取與資料庫

一 更新快取vs淘汰快取 1 更新快取 資料不但寫入資料庫,還會寫入快取。優點 快取不會增加一次miss,命中率高。2 淘汰快取 資料只會寫入資料庫,不會寫入快取,只會把資料淘汰掉。優點 簡單。3 如何選擇呢 更新的代價不是太大則更新快取,否則淘汰快取。二 先運算元據庫vs先操作快取 1 如何選擇 ...

MySql資料庫 58沈劍 架構師之路

innodb,5項最佳實踐,知其所以然?innodb行鎖,如何鎖住一條不存在的記錄?innodb併發如此高,原因竟然在這?innodb,能將資料儲存在 裡?挖坑,innodb的七種鎖 插入innodb自增列,居然是表鎖?innodb併發插入,居然使用意向鎖?innodb,select為啥會阻塞ins...