MySQL與Oracle中一致性讀的相同點與差異

2021-09-02 16:45:29 字數 2850 閱讀 4953

一、問題的提出

乙個操作執行select * from tb_trade_record where product_type = 『book』語句,假設表tb_trade_record初始時有1000000行資料,整個select過程持續10分鐘。會話1在8:00發起這個select操作(這時,滿足product_type = 『book』的記錄有10000條),8:02時,會話2向tb_trade_record表中插入了2條資料,且product_type = 『book』,並且已提交,會話1在8:10讀取完畢。那麼,會話1讀出的記錄是10000條,還是10002條?

二、什麼是一致性讀

關於上述問題的解答如下:

答案是:10000條,因為會話1是在8:00發起的,select操作應該從8:00那一刻的資料庫快照中讀取tb_trade_record表滿足條件滿足 product_type = 『book』的資料,而不論讀取操作花多少時間,期間資料發生什麼變化。因此不是讀取結束8:10時的資料,更不是其他中間時刻的資料。所以,上述問題的答案是10000。

讀取操作發起的那一刻是8:00,整個讀取操作應該都是從8:00那一刻的資料庫快照中讀取資料,這就是一致性讀或者快照讀。

三、mysql與oracle一致性讀的實現

1.mysql一致性讀的實現(innodb儲存引擎)

在每一行記錄的後面儲存兩個隱藏的列實現一致性讀。一列儲存行的建立時間或者說是系統版本號,另外一列儲存的是該行過期(刪除)時的時間或者系統版本號。每次開啟乙個新事務時,系統版本號就會遞增,事務開啟時刻的系統版本號就是該事務的版本號。

針對select、insert、delete、update操作的具體實施如下:

select:

innodb會根據以下條件檢查每行記錄:

a.查詢版本號小於等於當前事務的系統版本號,這樣確保當前事務讀取的行是在當前事務開啟前已經存在,或者當前事務插入或者修改過的資料。

b.行刪除時的版本要麼沒有,要麼大於當前事務的版本號(不能等於,等於表示是當前事務刪除的),這樣確保當前事務讀取到的行在當前事務開始之前還沒有被刪除。

insert:

新插入的行將當前事務的系統版本號作為該行的版本號。

delete:

刪除的行儲存當前事務的系統版本號作為該行的版本號。

update:

update時插入一行新記錄,儲存當前事務的系統版本號作為該行的版本號,同時儲存當前事務的系統版本號作為原來行的過期時的系統版本號。

儲存兩個隱藏的列資料,使得大多數讀操作都可以不用加鎖,這樣讀操作簡單,併發效能好,不用鎖表,保證只會讀取到符合要求的行。

2.oracle一致性讀的實現

a.塊中記錄scn(system change number),scn是乙個只增不減的數字,每行記錄就儲存在塊中。當塊的內容改變,scn就會增加。

b.塊提供itl(interested transaction list),如果更新了某條記錄,該更新操作對應的事務就會被寫進該記錄所在塊的itl中,如果事務沒有提交或者回滾了,則塊中就存在活動事務,資料庫可識別出這種情況。

oracle基於scn和itl來實現一致性讀。

四、相同點與差異

1. 相同點:

mysql基於每行資料的建立時系統版本號和刪除時系統版本號來實現一致性讀;oracle基於scn和itl來實現一致性讀。雖然名稱及實現方式不一樣,但是它們都是實現mvcc(multi-version concurrency control多版本併發控制)。mvcc在很多情況下避免了加鎖操作,實現非阻塞的讀,提高併發操作的效能。它的實現是通過儲存資料在某個時間點的快照來實現,不管讀取操作執行多長時間,每個事務看到的資料都是一致的。

a.都是將一行資料與另外乙個或者兩個資料關聯起來,mysql是在一行記錄中增加兩個隱藏列,乙個是建立時版本號,乙個是刪除時版本號;oracle通過在行記錄所在的邏輯塊(oracle的資料檔案由若干個tablespace組成,乙個tablespace由若干個segment組成,乙個segment由若干個extent組成,乙個extent由若干個block組成,資料表的每行記錄就是儲存在block裡面)中,在這個塊中除了儲存資料記錄外,還儲存和這個記錄相關的scn和itl,這樣一行資料記錄就和scn、itl關聯起來。

b.都是通過比較乙個數字來進行是否需要讀取該行資料的。mysql通過比較建立時系統版本號來判斷,oracle通過比較scn來判斷。如果讀取期間發生了刪除或者更新,mysql使用刪除時系統版本號找到之前的記錄,oracle通過itl來在undo日誌裡面找到前記錄。

c.都需要額外的儲存空間來儲存額外的字段。

2. 差異:

a. 系統設計上的差異:mysql是直接在一行資料內記錄版本號,oracle在資料內容外記錄,然後再與內容關聯起來。

b.對於查詢期間,刪除或者更新記錄的前記錄的查詢凡是不同。更新或者刪除時,mysql是新增一條記錄,設定原紀錄的刪除版本號。oracle刪除時是在undo日誌裡面記錄反向的update操作或者insert操作,因此查詢更新或者刪除的記錄的方式不同

五、總結

mysql和oracle都實現了基於mvcc的一致性讀,實現方式不同,但目的相似,替代鎖操作,提高了併發操作效能。

mysql(innodb儲存引擎)實現mvcc,但只能在repeatable read(解決不可重複讀) 和read committed(解決髒讀)兩個隔離級別下工作。

oracle是在其邏輯體系結構(tablespace、segment、extent、block)的基礎上實現的一致性讀。

六、參考

1. 《高效能mysql》,電子工業出版社

2. 《收貨,不止oracle》,電子工業出版社

mysql 強一致性 Mysql高一致高可用方案

一句話總結 使用官方mysql innodb cluster集群方案實現mysql冗餘備份,無單點故障的高可用性。專案背景 1 對資料可用性要求高,要求多節點冗餘備份,mysql單點故障後可以切換到其他節點 2 對資料準確性要求高,對mysql寫資料時,需要強一致性備份,不能是非同步的備份 3 併發...

mysql事務中一致性和原子性的區別

大體含義就是,事務的產生,其實是為了當應用程式訪問資料庫的時候,事務能夠簡化我們的程式設計模型,不需要我們去考慮各種各樣的潛在錯誤和併發問題.可以想一下當我們使用事務時,要麼提交,要麼回滾,我們不會去考慮網路異常了,伺服器宕機了,同時更改乙個資料怎麼辦對吧.因此事務本質上是為了應用層服務的.而不是伴...

redis與mysql一致性方案解析

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作 但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議 本文由以下三個部分組成 1 講解快取更新策略 2 ...