MySQL 5.6 5.7 如何自定義行鎖超時等待(wait timeout)時間 innodb_lock_wait_timeout

1. 問題

最近由于業(yè)務(wù)的需要,寫了個基于數(shù)據(jù)庫鎖機(jī)制的分布式調(diào)度簡易框架,用于處理業(yè)務(wù)中的補(bǔ)償任務(wù)和定時輪詢?nèi)蝿?wù)。由于調(diào)度任務(wù)處理時間長短不一,有些是幾秒處理完,而有些需要好幾分鐘。對于處理時間較長的任務(wù),在事務(wù)中,行鎖會一直占據(jù)直到事務(wù)處理結(jié)束。

那么問題就來了,對于時間處理較長的任務(wù),再下一輪調(diào)度起來之前事務(wù)還沒處理完,這個時候,下個事務(wù)會在行鎖上一直等待下去,直到timeout。這樣會占據(jù)多個線程、消耗多數(shù)數(shù)據(jù)庫資源。

2. 解決思路、方案

思路也很簡單,當(dāng)檢測到數(shù)據(jù)庫行鎖被占據(jù)時,當(dāng)前線程立馬結(jié)束,不進(jìn)行鎖釋放等待,這樣既節(jié)約線程資源也節(jié)省數(shù)據(jù)庫資源。

我們知道,MySQL8是支持 'SELECT ... for update NOWAIT' 這種寫法的,但是對于5.x版本這種寫法并不支持(圖 - 1),恰巧我們用的是5.6版本,我們需要另外想辦法來解決。

圖 - 1

思路1: 在MYSQL系統(tǒng)變量里面(global variable, session variable)中有特定的變量用來控制這個行鎖超時等待時間,我們可以修改這變量值,來使得我們的等待超時時間縮短

思路2: 比較好的方案,我們只修改當(dāng)前會話的,而不修改全局變量值(有可能多個程序在連你的數(shù)據(jù)庫)

思路3: 到底哪個變量控制這行鎖的超時等待時間呢?通過網(wǎng)上查詢,我們可以知道有一個叫 'innodb_lock_wait_timeout' 的變量正是我們要尋找的東東。 MySQL對于超時相關(guān)的變量有很多,大家可以查詢information_scheme.global/session_variables表 (5.7版本略微不同,需要在performance_schema去查詢):

select * from information_schema.global_variables where variable_name like '%timeout%';

你會看到有很多相關(guān)的變量,每個變量的含義,大家可以網(wǎng)上查找一下,了解一下很有必要!!這里我們只關(guān)心 「innodb_lock_wait_timeout」這個變量,默認(rèn)值是 50秒,表示: 行鎖等待超時時間是50秒。

圖 - 2

好了,問題根源我們也找到,現(xiàn)在的問題是怎么做?!

思路1:數(shù)據(jù)庫的操作流程其實(shí)也挺直接明了的:

定義DataSource -> 從DS池中獲取Connection -> 通過connection執(zhí)行SQL

涉及到事務(wù)的,其實(shí)也就是在第二步獲取connection后在執(zhí)行第三部前,執(zhí)行事務(wù)相關(guān)操作(在動態(tài)代理中),比如:執(zhí)行 begin語句(start transaction語句效果也一樣)

思路2:我們能否在Connection創(chuàng)建的時候,就把 innodb_lock_wait_timeout的值給修改了呢?答案是可以的。

Springboot中默認(rèn)的數(shù)據(jù)庫連接池用的是 Hikari,而它剛好有可配置屬性:connectionInitSql,通過代碼跟蹤,可以知道這個SQL在創(chuàng)建connection的時候會被執(zhí)行。這個正好是我們想要的?。。?!好了,其他不多說了,上代碼吧?。?/p>

通過 SET語句,我們可以設(shè)置SESSION級別的值(圖 - 3)

圖 - 3

3. 測試用例

圖 - 4

4. 總結(jié)

這個問題,項(xiàng)目中存在有一段時間了,一直都沒有時間沉下心來研究,這周趁著項(xiàng)目空閑期終于搞出了這個方案,下周上線,線上觀察一段時間。

5. 附圖

有同學(xué)問及到有關(guān)方法的代碼,現(xiàn)黏貼一下:

lockAgain()方法

附圖1

lockRowFor1000Seconds()方法

附圖2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、概述 數(shù)據(jù)庫鎖定機(jī)制簡單來說,就是數(shù)據(jù)庫為了保證數(shù)據(jù)的一致性,而使各種共享資源在被并發(fā)訪問變得有序所設(shè)計(jì)的一種...
    不變甄心閱讀 2,807評論 0 3
  • https://blog.csdn.net/steven_liwen/article/details/531884...
    SkTj閱讀 2,465評論 0 16
  • 今天看到一位朋友寫的mysql筆記總結(jié),覺得寫的很詳細(xì)很用心,這里轉(zhuǎn)載一下,供大家參考下,也希望大家能關(guān)注他原文地...
    信仰與初衷閱讀 4,833評論 0 30
  • 文章導(dǎo)讀: 累兮,累兮,要死兮...... 本文解決問題: 1、表級鎖定(讀鎖、寫鎖) 2、行級鎖定(共享鎖、排他...
    創(chuàng)造new_world閱讀 706評論 0 1
  • 最近碰到幾個業(yè)務(wù)場景,會遇到并發(fā)的問題。在單實(shí)例情況下,我們會通過java.util.concurrent包...
    菜鳥小玄閱讀 2,315評論 0 5

友情鏈接更多精彩內(nèi)容