技術實踐丨列存表並發更新時的鎖等待問題原理


摘要:當開啟transaction,執行updata的語句執行成功,不執行commit或rollback;再開啟另一個窗口,執行upadate語句,會出現失敗(報錯:鎖等待超時)的情況,但是如果對於上一個窗口執行rollback,此窗口update可以執行成功,該種情況應考慮該表是否為列存表。

當開啟transaction,執行updata的語句執行成功,不執行commit或rollback;再開啟另一個窗口,執行upadate語句,會出現失敗(報錯:鎖等待超時)的情況,但是如果對於上一個窗口執行rollback,此窗口update可以執行成功,該種情況應考慮該表是否為列存表。

【問題根因】

如果使用的是列存表,在事務中執行update操作時,是以CU為單位進行加鎖的,所以在事務未提交時並發更新同一CU的其他數據時會出現鎖等待的情況,等待超時的時候會出現報錯

【機制原理】

1.CU為壓縮單元(Compress Unit),列存儲的最小單位,導入數據時生成,生成后數據固定不可更改,單個CU最多存儲1列60000行數據。同一列的CU連續存儲在一個文件中,當大於1G時,切換到新文件中。其中的Ctid字段標識列存表的一行,由cu_id和CU內行號(cu_id, offset)組成;一次性寫入的多條的數據位於同一CU。

2. 為了防止頁面同一個元組被兩個事務同時更新,在進行update時,都會加上行級鎖,對於行存來說是對一行數據加鎖,對於列存來說就是對一個CU加鎖,當一個事務update未提交時,其他事務是無法同時去更新同一CU的數據的。

3.進行update操作后,舊元組被標記為deleted,新元組會寫到一個新的CU中

【案例分析】

1.根據現場的報錯信息,可以確定是並發更新報錯;進行update時,會申請行級鎖,在申請行級鎖之前會申請transactionid鎖,等待超時后報錯信息為:waiting for ShareLock on transaction xxx after ..ms

2. 客戶反應更新的並不是同一條數據,id不同,詢問客戶后得知出現問題的是列存表,查詢更新的數據是否處於同一CU。

查詢后發現處於同一CU,符合預期。

3. 本地場景復現:

起事務執行update操作:

事務未提交並發更新數據出現等待:

查詢后發現兩條數據位於同一cu:

【相關問題】

為什么update成功一次之后,下一次update就不會互相等鎖了?

這是因為update成功之后,舊數據被標記為deleted,新數據寫入新的CU,這兩條數據不再是同一個CU了,也就不存在這種鎖沖突

【處理方案】

列存表不適合頻繁的update場景,列存頻繁的update容易觸發並發更新等鎖超時,並且會導致小CU過多,而每個CU都會擴展至8192字節進行對齊,從而導致磁盤空間迅速膨脹;頻繁的點查或頻繁update場景建議使用行存表。

 本文分享自華為雲社區《列存表並發更新時時的鎖等待問題原理》,原文作者:PFloyd 。

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

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



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