記錄一次踩到MySQL8官方BUG的經歷

2020-10-28 12:00:42

版權說明: 本文由博主原創,轉載請註明出處。
原文地址: https://blog.csdn.net/qq_38688267/article/details/109313764

背景介紹

       前些天完成伺服器上雲工作,在做資料遷移的是同時也將MySQL5.7.29升級到了MySQL8.0.19。上雲工作也寫了一篇部落格記錄:>>傳送門<<

       在正式上雲之前,我們先同步了一次資料進行測試,排查升級MySQL後出現功能異常的情況。MySQL理論上是向下相容的,我們也的確沒有出現SQL報錯等情況。

       但是在上線運營兩天後發現有幾條類似的SQL的執行效率明顯下降。

 

問題排查

       首先我們來看看是條什麼樣的SQL吧:

SELECT DISTINCT `區域` FROM `服務單` limit 0,200;

       你沒有看錯,表名和欄位名都是中文!可能有些疾惡如仇的小夥伴情緒瞬間就上來了,容我解釋一下:管理這些表的人在我們這的職位是平臺資料分析崗,簡單來說就是做一些資料包表,業績/資料月報年報啥的,他們以前都是用EXCEL,所以相當於是以一個小白的身份來運算元據庫的,所以對他們來說用起來就行,管它?

       我剛來的時候,也曾提醒過他們,跟他們講一些表設計的東西啥的,講得最多的是怎麼優化SQL,但是跟他們講半天,轉頭還是那樣,我就隨他們了,反正他們的資料庫跟系統的資料庫是分開的,隨他們弄吧。沒想到這次給我挖了這麼大一個坑。

       廢話就不多說了,我們先來看看SQL的執行計劃吧:

在這裡插入圖片描述
       5.7.298.0.19的執行計劃一樣,但是5.7.29執行這條SQL只要1.8s8.0.19執行則需要9s。這讓我覺得莫名其妙,升級版本後相同的執行計劃下MySQL8居然比MySQL5.7慢?

TIPS:
       雖然MySQL8在各方面效能都明顯優於低版本;但在某些情況下,MySQL8MySQL5.7-再執行同一條SQL時,可能由於優化器的選擇不同,MySQL8執行效率反而低於低版本的。比如MySQL8可能不走索引,而低版本選擇走索引等。

       執行計劃一樣,就說明不是SQL的問題。當然,如果給欄位加索引什麼的肯定也能提高查詢效率,但是我們這次的問題不僅僅是為了解決這一條SQL的慢,好幾條SQL都這樣,只是表名或欄位名不一樣。所以我們得找到治本的辦法。

 

嘗試解決

       我最先想到的是環境變數,因為這個MySQL8是我新搭的,跟以前的資料庫的引數肯定有不同的地方,所以我就一一排查了一遍MySQL的設定。關於影響MySQL效能的環境變數我也寫了一篇部落格:>>傳送門<<

       弄了好一陣,把所有引數有設定成一模一樣,稍微好了一點點,執行時間變成了7s,但還遠遠不夠。那麼除了環境變數還有啥能改的呢?

       我們再來看看錶結構:

在這裡插入圖片描述
        哦豁!排序規則 不一樣!莫不就是這個原因?可把我高興壞了,就開始測試,換了好幾種排序規則,結果發現根本沒區別。。。

TIPS:
        MySQL8中增加了幾種排序規則,比如utf8mb4utf8mb4_0900_ai_ci,這個規則在MySQL5.7中是不存在的。不同的排序規則對查詢SQL有一定影響,比如在沒有order by子句的SQL中,不同的排序規則可能返回值順序不一樣。
       在我另外一篇關於 MySQL5.7和8.0索引失效情況整理 的部落格中也有提到,不同排序規則的兩張表的欄位做關聯的時候可能會導致索引失效甚至直接報錯!>>傳送門<<
        千萬不要忽略排序規則!

        搞到這裡,我實在是想不通還有什麼能改的了,我只能認為我安裝的時候安裝出錯了,裝了個假MySQL。所以我就把這張表同步到我原生的MySQL8.0.20上面測試,發現還是一樣需要7s

        行吧,畢竟windows和Linux可能有區別,我就在雲伺服器上用Docker又裝了個MySQL8.0.20進行測試,發現還是不行。。。

       到此,我意識到這個問題超綱了!~,所以我就到QQ裡面的MySQL交流群裡面請教,有個大佬幫我弄了半天,他也蒙了,然後他把表資料同步到他原生的MySQL8.0.21中進行測試,居然只要1.6s

       大佬跟我說他的是OK的時候,我的心情是這樣的:

在這裡插入圖片描述

 

       憑啥?一陣無語後,我也意識到八成是版本的問題了,抱著半信半疑的心態,我又用Docker裝了個最新的MySQL8.0.22(Docker映象中最新),同步資料過去一測,果然!1.6s,是可以的!

       到此,總算是把這個問題解決了!花了我整整兩天!這兩天我中午都沒有休息!別人睡午覺,我在抓耳撓腮!

       翌日,大佬也找到了問題所在:MySQL的官方BUG! 從TempTable儲存引擎釋放記憶體時,塊大小計算不正確,從而導致SELECT DISTINCT查詢效能下降。 這個BUG在MySQL8.0.21中被修復。哇,我好氣啊~~~

在這裡插入圖片描述

相關連線:
       相同問題反饋:https://bugs.mysql.com/bug.php?id=99593
       上圖原文地址:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-21.html

 
       後面又弄了一天,同步資料啥的,這件事總算是弄完了。太難了!幾十年的MySQL的BUG都能被我遇到!

       希望本文對大家有所幫助或啟發。碼字不易,覺得寫的不錯的可以點贊支援一下哦~