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

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

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

當開啓transaction,執行updata的語句執行成功,不執行commit或rollback;再開啓另外一個窗口,執行upadate語句,會出現失敗(報錯:鎖等待超時)的狀況,可是若是對於上一個窗口執行rollback,此窗口update能夠執行成功,該種狀況應考慮該表是否爲列存表。併發

【問題根因】

若是使用的是列存表,在事務中執行update操做時,是以CU爲單位進行加鎖的,因此在事務未提交時併發更新同一CU的其餘數據時會出現鎖等待的狀況,等待超時的時候會出現報錯spa

【機制原理】

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

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

3.進行update操做後,舊元組被標記爲deleted,新元組會寫到一個新的CU中get

【案例分析】

1.根據現場的報錯信息,能夠肯定是併發更新報錯;進行update時,會申請行級鎖,在申請行級鎖以前會申請transactionid鎖,等待超時後報錯信息爲:waiting for ShareLock on transaction xxx after ..msit

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

查詢後發現處於同一CU,符合預期。社區

3.本地場景復現:class

起事務執行update操做:
image.png

事務未提交併發更新數據出現等待:
image.png

查詢後發現兩條數據位於同一cu:
image.png

【相關問題】

爲何update成功一次以後,下一次update就不會互相等鎖了?

這是由於update成功以後,舊數據被標記爲deleted,新數據寫入新的CU,這兩條數據再也不是同一個CU了,也就不存在這種鎖衝突

【處理方案】

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

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

相關文章
相關標籤/搜索