2021-02-26 分類: 網站建設
前幾天,線上發生了一次數據庫死鎖問題,這一問題前前后后排查了比較久的時間,這個過程中自己也對數據庫的鎖機制有了更深的理解。
updateFundStreamId 執行的時候使用到的是 PRIMARY 索引。
updateStatus 執行的時候使用到的是 idx_seller_transNo 索引。
通過執行計劃,我們發現 updateStatus 其實是有兩個索引可以用的,執行的時候真正使用的是 idx_seller_transNo 索引。這是因為 MySQL 查詢優化器是基于代價(cost-based)的查詢方式。
因此,在查詢過程中,最重要的一部分是根據查詢的 SQL 語句,依據多種索引,計算查詢需要的代價,從而選擇最優的索引方式生成查詢計劃。
我們查詢執行計劃是在死鎖發生之后做的,事后查詢的執行計劃和發生死鎖那一刻的索引使用情況并不一定是相同的。
但是,我們結合死鎖日志,也可以定位到以上兩條 SQL 語句執行的時候使用到的索引。
即 updateFundStreamId 執行的時候使用到的是 PRIMARY 索引,updateStatus 執行的時候使用到的是 idx_seller_transNo 索引。
有了以上這些已知信息,我們就可以開始排查死鎖原因及其背后的原理了。
通過分析死鎖日志,再結合我們的代碼以及數據庫建表語句,我們發現主要問題出在我們的 idx_seller_transNo 索引上面:
- KEY `idx_seller_transNo` (`seller_id`,`fund_transfer_order_no`(20))
索引創建語句中,我們使用了前綴索引,為了節約索引
那么為什么 fund_transfer_order_no 的前 20 位相同會導致死鎖呢?
加鎖原理
我們就拿本次的案例來看一下 MySQL 數據庫加鎖的原理是怎樣的,本文的死鎖背后又發生了什么。
我們在數據庫上模擬死鎖場景,執行順序如下:
我們知道,在 MySQL 中,行級鎖并不是直接鎖記錄,而是鎖索引。索引分為主鍵索引和非主鍵索引兩種:
主鍵索引的葉子節點存的是整行數據。在 InnoDB 中,主鍵索引也被稱為聚簇索引(Clustered Index)。
非主鍵索引的葉子節點的內容是主鍵的值,在 InnoDB 中,非主鍵索引也被稱為非聚簇索引(Secondary Index)。
所以,本文的示例中涉及到的索引結構(索引是 B+ 樹,簡化成表格了)如圖:
死鎖的發生與否,并不在于事務中有多少條 SQL 語句,死鎖的關鍵在于:兩個(或以上)的 Session 加鎖的順序不一致。
當前標題:解決線上數據庫死鎖,就是這么簡單!
鏈接分享:http://m.newbst.com/news29/103129.html
成都網站建設公司_創新互聯,為您提供外貿網站建設、品牌網站制作、營銷型網站建設、網站內鏈、網站導航、網站營銷
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯
猜你還喜歡下面的內容