一次Mysql?update?sql不當(dāng)引起的生產(chǎn)故障記錄
故障表現(xiàn)
一方面 :在阿里云控制臺(tái)云數(shù)據(jù)庫(kù)PolarDB對(duì)應(yīng)的集群管理頁(yè)面上,在診斷與優(yōu)化模塊里面的一鍵診斷會(huì)話管理中,發(fā)現(xiàn)某條update sql 執(zhí)行時(shí)間非常久且非常頻繁;
另一方面:業(yè)務(wù)監(jiān)控系統(tǒng)中開(kāi)始不斷有業(yè)務(wù)執(zhí)行時(shí)間發(fā)出告警信息提示,且告警的業(yè)務(wù)數(shù)據(jù)不斷上升,部分操作影響客戶(hù)使用。
業(yè)務(wù)背景
由于業(yè)務(wù)操作涉及到的業(yè)務(wù)流比較復(fù)雜,對(duì)純技術(shù)的分享來(lái)看,不是重點(diǎn)討論的話,為了更有利于理解問(wèn)題發(fā)生的原因,使用類(lèi)比的方式,把復(fù)雜的業(yè)務(wù)類(lèi)比成如下描述: 有數(shù)據(jù)庫(kù)3張表,第一張表t_grandfather (爺表),第二張表為t_father(父表),第三張表t_grandson(子孫表),DDL如下:
CREATE TABLE `t_grandfather ` ( `id` int(11) NOT NULL AUTO_INCREMENT, `count` int(11) NOT NULL DEFAULT 0 COMMENT '子孫后代數(shù)量', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爺表'; CREATE TABLE `t_father ` ( `id` int(11) NOT NULL AUTO_INCREMENT, `grandfather_id` int(11) NOT NULL COMMENT '老爺表id', PRIMARY KEY (`id`), KEY `idx_grandfather_id` (`grandfather_id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爸表'; CREATE TABLE `t_grandson` ( `id` int(11) NOT NULL AUTO_INCREMENT, `grandfather_id` int(11) NOT NULL COMMENT '老爺表id', PRIMARY KEY (`id`), KEY `idx_grandfather_id` (`grandfather_id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='孫子表';
三張表之間的業(yè)務(wù)邏輯關(guān)系為,先生成老爺表,然后這個(gè)老爺取很多老婆(業(yè)務(wù)),會(huì)不斷的生娃,生一個(gè)娃就會(huì)生成一張老爸表,同時(shí)會(huì)更新老爺表的count=count+1,表示新增一個(gè)后代了,老爺?shù)睦掀牛I(yè)務(wù))在不斷的生娃的時(shí)候,之前的生的娃也會(huì)有老婆,他們的老婆也會(huì)生娃,對(duì)老爺來(lái)說(shuō),就是它有了孫子(產(chǎn)生新的業(yè)務(wù)數(shù)據(jù)),那有了孫子之后也需要更新老爺表的count=count+1,表示新增一個(gè)后代了,以此類(lèi)推,子子孫孫無(wú)窮盡也(業(yè)務(wù)數(shù)據(jù)不斷生成) 如下圖所示:
祖?zhèn)鞔a的邏輯為,只要是t_father表和t_grandson有新增,就去更新t_grandfather。這個(gè)邏輯設(shè)計(jì)上問(wèn)題不大,不過(guò)考慮到孫子表數(shù)據(jù)量很猛的時(shí)候,這里就會(huì)出現(xiàn)一個(gè)非常嚴(yán)重的性能問(wèn)題。以下是業(yè)務(wù)摘取的一部分偽代碼
/** * 處理 father 的業(yè)務(wù) */ public void doFatherBusiness (){ //do fatherBusiness baba .... 此處省 // 插入 t_father 表 if (fatherMapper.inster(father)){ //update t_grandfather set count=count+1 where id= #{grandfatherId} grandfatherMapper.updateCount(father.getGrandfatherId ()) ; } } /** * 處理 grandson 的業(yè)務(wù) */ public void doGrandsonBusiness (){ //do grandson baba .... 此處省略 // 插入 t_grandson 表 if(grandsonMapper.inster(grandson)){ //update t_grandfather set count=count+1 where id= #{grandfatherId} grandfatherMapper.updateCount(grandson.getGrandfatherId()); } }
當(dāng)多個(gè)業(yè)務(wù)(線程)分別調(diào)用上面的方法時(shí),都會(huì)對(duì)t_grandfather表的更新操作造成巨大的壓力,特別是更新同一個(gè)id的情況下,mysql server內(nèi)部對(duì)鎖的競(jìng)爭(zhēng)非常激烈。最后表現(xiàn)出來(lái)就如前文背景描述的一致。
解決方案
1. 臨時(shí)處理方案:
一方面,在阿里云控制臺(tái),對(duì)sql進(jìn)行限流,在正常阻塞的會(huì)話,強(qiáng)制kill掉,讓數(shù)據(jù)的線程不阻塞著,釋放資源,另外一方面,在把接收請(qǐng)求的服務(wù)減少節(jié)點(diǎn)數(shù),目的是減少業(yè)務(wù)數(shù)據(jù)量進(jìn)入;
2. 長(zhǎng)久方案
一方面更改掉上面的業(yè)務(wù)邏輯,插入t_grandson表和t_father表時(shí),不在去更新t_grandfather表的count字段;另一方面,需要用到count統(tǒng)計(jì)需求時(shí),全部切換成別的方式;
總結(jié)
到此這篇關(guān)于一次Mysql update sql不當(dāng)引起的生產(chǎn)故障的文章就介紹到這了,更多相關(guān)Mysql update sql生產(chǎn)故障內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mysql優(yōu)化之Zabbix分區(qū)優(yōu)化
這篇文章主要介紹了Mysql優(yōu)化中Zabbix分區(qū)優(yōu)化的詳細(xì)方法和優(yōu)缺點(diǎn)分析,一起學(xué)習(xí)下。2017-11-11Mysql中STR_TO_DATE函數(shù)使用(字符串轉(zhuǎn)為日期/時(shí)間值)
這篇文章主要給大家介紹了關(guān)于Mysql中STR_TO_DATE函數(shù)使用的相關(guān)資料,STR_TO_DATE函數(shù)的主要功能是字符串轉(zhuǎn)為日期/時(shí)間值,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09Windows10下mysql 8.0.19 winx64安裝教程及修改初始密碼
這篇文章主要為大家詳細(xì)介紹了Windows10下mysql 8.0.19 winx64安裝教程及修改初始密碼,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02MySQL各個(gè)特殊時(shí)間段的查詢(xún)方法
在MySQL數(shù)據(jù)庫(kù)中,經(jīng)常需要查詢(xún)某個(gè)時(shí)間段內(nèi)的數(shù)據(jù),所以本文給大家介紹了MySQL各個(gè)特殊時(shí)間段的查詢(xún)方法,并提供相應(yīng)的源代碼示例,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01ubuntu安裝mysql數(shù)據(jù)庫(kù)方法
ubuntu基于linux的免費(fèi)開(kāi)源桌面PC操作系統(tǒng),十分契合英特爾的超極本定位,支持x86、64位和ppc架構(gòu)。這篇文章給大家介紹ubuntu安裝mysql數(shù)據(jù)庫(kù)方法,非常不錯(cuò),需要的朋友參考下吧2019-08-08mysql 5.7.21 winx64綠色版安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了mysql 5.7.21 winx64綠色版安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09Mysql數(shù)據(jù)庫(kù)手動(dòng)及定時(shí)備份步驟
最近剛好用到了數(shù)據(jù)庫(kù)備份,想著還有個(gè)別實(shí)習(xí)或者剛工作的小伙伴一個(gè)drop不小心刪表、刪庫(kù),心內(nèi)慌得一批不知道該怎么辦,就打算跑路了,學(xué)會(huì)這個(gè)小技巧就不用跑路了2021-11-11MySQL自動(dòng)為查詢(xún)數(shù)據(jù)結(jié)果加序號(hào)
這篇文章主要給大家介紹了關(guān)于MYSQL如何自動(dòng)為查詢(xún)數(shù)據(jù)的結(jié)果編上序號(hào)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mysql具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧2022-12-12