如何避免長(zhǎng)事務(wù)對(duì)業(yè)務(wù)的影響?
預(yù)熱
比較喜歡的一段話:不經(jīng)一番寒徹骨,怎得梅花撲鼻香,學(xué)習(xí)是枯燥的請(qǐng)大家堅(jiān)持!
大家好前面我們大概了解了關(guān)于事務(wù)的隔離級(jí)別,實(shí)現(xiàn)方式,啟動(dòng)方式的細(xì)節(jié),長(zhǎng)事務(wù)與短事務(wù)的區(qū)別。今天我們延伸介紹一下,如果因?yàn)槭д`用了長(zhǎng)事務(wù),那我們?cè)诠ぷ髦腥绾伟l(fā)現(xiàn)問(wèn)題,排查問(wèn)題?
開(kāi)始
這個(gè)問(wèn)題,我們可以從應(yīng)用開(kāi)發(fā)端和數(shù)據(jù)庫(kù)端來(lái)看。
首先,從應(yīng)用開(kāi)發(fā)端來(lái)看:
確認(rèn)是否使用了 set autocommit=0。這個(gè)確認(rèn)工作可以在測(cè)試環(huán)境中開(kāi)展,把 MySQL 的 general_log 開(kāi)起來(lái),然后隨便跑一個(gè)業(yè)務(wù)邏輯,通過(guò) general_log 的日志來(lái)確認(rèn)。一般框架如果會(huì)設(shè)置這個(gè)值,也就會(huì)提供參數(shù)來(lái)控制行為,你的目標(biāo)就是把它改成 1 (自動(dòng)提交)。
確認(rèn)是否有不必要的只讀事務(wù)。有些框架會(huì)習(xí)慣不管什么語(yǔ)句先用 begin/commit 框起來(lái)。我見(jiàn)過(guò)有些是業(yè)務(wù)并沒(méi)有這個(gè)需要,但是也把好幾個(gè) select 語(yǔ)句放到了事務(wù)中。這種只讀事務(wù)可以去掉。
業(yè)務(wù)連接數(shù)據(jù)庫(kù)的時(shí)候,根據(jù)業(yè)務(wù)本身的預(yù)估,通過(guò) SET MAX_EXECUTION_TIME 命令,來(lái)控制每個(gè)語(yǔ)句執(zhí)行的最長(zhǎng)時(shí)間,避免單個(gè)語(yǔ)句意外執(zhí)行太長(zhǎng)時(shí)間。具體的意外我們后續(xù)再介紹
其次,從數(shù)據(jù)庫(kù)端來(lái)看:
監(jiān)控 information_schema.Innodb_trx 表,設(shè)置長(zhǎng)事務(wù)閾值,超過(guò)就報(bào)警 / 或者 kill;
Percona 的 pt-kill 這個(gè)工具不錯(cuò),推薦使用;
在業(yè)務(wù)功能測(cè)試階段要求輸出所有的 general_log,分析日志行為提前發(fā)現(xiàn)問(wèn)題;
如果使用的是 MySQL 5.6 或者更新版本,把 innodb_undo_tablespaces 設(shè)置成 2(或更大的值)。如果真的出現(xiàn)大事務(wù)導(dǎo)致回滾段過(guò)大,這樣設(shè)置后清理起來(lái)更方便。
