您好,登錄后才能下訂單哦!
這篇文章主要介紹“Mysql update sql引起的生產故障怎么解決”,在日常操作中,相信很多人在Mysql update sql引起的生產故障怎么解決問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Mysql update sql引起的生產故障怎么解決”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
一方面 :在阿里云控制臺云數據庫PolarDB對應的集群管理頁面上,在診斷與優化模塊里面的一鍵診斷會話管理中,發現某條update sql 執行時間非常久且非常頻繁;
另一方面:業務監控系統中開始不斷有業務執行時間發出告警信息提示,且告警的業務數據不斷上升,部分操作影響客戶使用。
由于業務操作涉及到的業務流比較復雜,對純技術的分享來看,不是重點討論的話,為了更有利于理解問題發生的原因,使用類比的方式,把復雜的業務類比成如下描述: 有數據庫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 '子孫后代數量', 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='孫子表';
三張表之間的業務邏輯關系為,先生成老爺表,然后這個老爺取很多老婆(業務),會不斷的生娃,生一個娃就會生成一張老爸表,同時會更新老爺表的count=count+1,表示新增一個后代了,老爺的老婆(業務)在不斷的生娃的時候,之前的生的娃也會有老婆,他們的老婆也會生娃,對老爺來說,就是它有了孫子(產生新的業務數據),那有了孫子之后也需要更新老爺表的count=count+1,表示新增一個后代了,以此類推,子子孫孫無窮盡也(業務數據不斷生成) 如下圖所示:
祖傳代碼的邏輯為,只要是t_father表和t_grandson有新增,就去更新t_grandfather。這個邏輯設計上問題不大,不過考慮到孫子表數據量很猛的時候,這里就會出現一個非常嚴重的性能問題。以下是業務摘取的一部分偽代碼
/** * 處理 father 的業務 */ 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 的業務 */ 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()); } }
當多個業務(線程)分別調用上面的方法時,都會對t_grandfather表的更新操作造成巨大的壓力,特別是更新同一個id的情況下,mysql server內部對鎖的競爭非常激烈。最后表現出來就如前文背景描述的一致。
1. 臨時處理方案:
一方面,在阿里云控制臺,對sql進行限流,在正常阻塞的會話,強制kill掉,讓數據的線程不阻塞著,釋放資源,另外一方面,在把接收請求的服務減少節點數,目的是減少業務數據量進入;
2. 長久方案
一方面更改掉上面的業務邏輯,插入t_grandson表和t_father表時,不在去更新t_grandfather表的count字段;另一方面,需要用到count統計需求時,全部切換成別的方式;
到此,關于“Mysql update sql引起的生產故障怎么解決”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。