5.7停服倒計時!關(guān)于MySQL升級到8.0版本的一些經(jīng)驗
一、如何看待MySQL版本升級
關(guān)于數(shù)據(jù)庫版本升級,一直都是熱議話題,對于升級的緣由各家也有所不同,有業(yè)務驅(qū)動的,有DBA自發(fā)驅(qū)動的,有規(guī)劃導向也有方向指引的……拋開各種原因,當升級這個決定落下來的時候,對于DBA手頭的幾百幾千套數(shù)據(jù)庫來說,就好比是一場動物大遷徙,滿滿的畫面感。
從Oracle發(fā)布的版本生命周期規(guī)劃可以看到,MySQL5.7已經(jīng)走到了生命周期的終點,意味著后續(xù)將不再為 MySQL 5.7 提供官方更新、錯誤修復或安全補丁。
圖片
阿里云和AWS都在官方公布了版本支持計劃,MySQL 5.7版本已經(jīng)開始了倒計時。
圖片
而要想讓這件事情獲得研發(fā)同學的大力支持,就需要平滑升級或者最低成本的改動。所以對于這場遷移的基本要求,我在心里默默對自己提了要求:零故障,平滑升級。
(一)行業(yè)內(nèi)的MySQL版本數(shù)據(jù)情況
我在2022年底左右調(diào)研了下行業(yè)內(nèi)的一些公司的MySQL數(shù)據(jù)庫版本情況,列表如下:
圖片
可以看到大部分的公司還是在MySQL 5.7這個版本,而且從服務規(guī)模來看,越是規(guī)模大的公司,要想做整體升級這個事情的復雜度就會高出幾個數(shù)量級。
(二)我們做數(shù)據(jù)庫版本升級的理由
我們做這件事情是從規(guī)劃導向來切入的,也有一部分DBA自驅(qū)的因素。說是規(guī)劃導向,轉(zhuǎn)義過來就是不打無準備之仗,MySQL后續(xù)的整體架構(gòu)是構(gòu)建在基礎(chǔ)存儲之上的,如果基礎(chǔ)存儲存在瓶頸,對于后續(xù)的架構(gòu)演進也存在明顯短板,所以我們在2019年底就開始調(diào)研并小范圍在新業(yè)務中試點MySQL 8.0了。
如下是早期調(diào)研中對于MySQL 8.0和MySQL 5.7使用sysbench壓測的一些信息供參考,可以看到MySQL 8.0是有明顯性能提升的。至于MySQL 8.0的版本,我們的考慮是和驗證測試的8.0.19保持一致,在后期支持新版本的無縫升級。
圖片
從功能上來說,開發(fā)特性更加豐富,SQL優(yōu)化效果和運維功能上都有明顯的提升,在兼容性方面會更加嚴格(兼容性嚴格具有兩面性)。
圖片
在經(jīng)過了一個相對穩(wěn)定的周期驗證之后,無論從穩(wěn)定性、性能和功能方面確實達到了預期的效果,有一些特性確實解決了當時的一些運維問題。
說是DBA自驅(qū)的理由,是因為我們盤點了一下近些年來的MySQL技術(shù)棧使用情況,發(fā)現(xiàn)實際的情況比我們預想的要差一些,比如MySQL 5.5我會定義為一個分支技術(shù)棧,以此類推,我們目前存在7個分支技術(shù)棧。
圖片
在這些因素的基礎(chǔ)之上,我們以點帶面展開分析,發(fā)現(xiàn)多分支技術(shù)棧散亂只是表象,還有一些潛在問題和瓶頸問題:
1、MySQL版本過舊,架構(gòu)管理不一致,運維復雜度較高
1) MySQL 5.5和5.6為過舊技術(shù)棧,官方已不再維護
2) 未來3年內(nèi)需要從MySQL 5.7升級至8.0,演進復雜度高
3) 40%操作系統(tǒng)版本過舊,后續(xù)的數(shù)據(jù)庫版本升級存在風險
2、部分技術(shù)棧已閉源,服務異常時存在恢復風險
1) Infobright已轉(zhuǎn)為商業(yè)版維護
2) TokuDB已于2020年不再維護
3、數(shù)據(jù)庫規(guī)范和審核機制難以支撐現(xiàn)有的業(yè)務需求
1) SQL審核工具解決了早期的研發(fā)規(guī)范問題,后續(xù)閉源難以持續(xù)
2) 數(shù)據(jù)庫開發(fā)規(guī)范已4年未更新,部分開發(fā)規(guī)范已難以滿足業(yè)務需要
4、人員穩(wěn)定性和持續(xù)發(fā)展
1)DBA不可避免地在做一些重復勞動,一些繁瑣的差異化操作勢必會削弱工作熱情,也會發(fā)生一些意料之外的異常
2)個人運維經(jīng)驗無法有效的沉淀轉(zhuǎn)化
所以這是一個綜合的問題,涉及到對技術(shù)、業(yè)務和人的管理,而且是環(huán)環(huán)相扣。
當然對于一件事情的基本邏輯越簡單,實現(xiàn)起來也更聚焦。所以我們進一步提煉了一下目標,7->2,即7個分支技術(shù)棧整合為2個,在這個基礎(chǔ)上進行生態(tài)技術(shù)棧的補充和完善。
(三)數(shù)據(jù)庫版本升級的意義
做這件事情有什么好處呢,也就是所謂的意義,我覺得是:降本增效,提高整體業(yè)務穩(wěn)定性。主要體現(xiàn)在如下六個方面:
- 應對未來3年內(nèi)的數(shù)據(jù)庫基礎(chǔ)服務風險,對后續(xù)的數(shù)據(jù)存儲平臺架構(gòu)迭代奠定基礎(chǔ)(這個需要由明確的規(guī)劃支撐)
- 通過版本升級提高整體業(yè)務性能和穩(wěn)定性
- 實現(xiàn)支持系統(tǒng)的一致性,提高基礎(chǔ)服務支撐能力
- 將單點業(yè)務遷移至MySQL主流技術(shù)棧,預防故障風險
- 對開發(fā)規(guī)范和SQL審核機制進行規(guī)范化支持和落地
- 為后續(xù)的環(huán)境標準化建設(shè)提供實踐經(jīng)驗
我從公有云和私有云的視角盤點了下MySQL技術(shù)棧發(fā)展的情況,其實MySQL 8.0已經(jīng)成為了行業(yè)主流的基線版本,各種數(shù)據(jù)庫產(chǎn)品層出不窮,如果基線版本已經(jīng)落后了,后續(xù)勢必會有整合和返工,所以這也算是一個技術(shù)的戰(zhàn)略點。在協(xié)議兼容的前提下,還需要進一步考慮到國產(chǎn)化數(shù)據(jù)庫的影子,當然也可以有更多的選擇,重心在于協(xié)議和生態(tài)技術(shù)棧兼容。
畢竟數(shù)據(jù)庫的升級是一項大工程,大開大合,研發(fā)同學再配合支持也需要權(quán)衡,所以MySQL 8.0的大版本基礎(chǔ)之上,在滿足驅(qū)動和協(xié)議兼容之后,后續(xù)的小版本和迭代升級計劃都是在8.0的體系之內(nèi)完全平滑閃斷完成,也就不需要研發(fā)同學全程跟進了。
(四)數(shù)據(jù)庫版本升級的潛在難點
當然任何事情都得多面看,看到好處(意義),也需要看到難點:
- 跨中心多團隊協(xié)作,周期較長
- 開發(fā)語言技術(shù)棧有7個,MySQL 8.0的驅(qū)動兼容性都需要充分考慮
- 部分升級改造需要研發(fā)側(cè)支持旁路數(shù)據(jù)雙寫
- 根據(jù)數(shù)據(jù)庫拓撲關(guān)聯(lián)主機業(yè)務的親和性,避免服務器故障
- 按照業(yè)務特點和優(yōu)先級制定差異化升級方案
- 基于滾動模式的數(shù)據(jù)庫資源全量替換,避免資源冗余
- 制定平滑的MySQL集群遷移方案,對業(yè)務侵入性最低
因為我們升級的基調(diào)是平滑模式,所以基本是資源平替,快速切換的實現(xiàn)策略,在這種情況下,每一個數(shù)據(jù)庫實例都需要反復確認,會有大量的溝通協(xié)調(diào)工作,況且業(yè)務不能停,因為數(shù)據(jù)庫升級直接影響到業(yè)務使用,這件事情的性質(zhì)也就變了。
二、通過五個方面保障數(shù)據(jù)庫升級的穩(wěn)定性
接下來我會從如下的幾個方面來保障整個升級過程的穩(wěn)定性。
(一)梳理和確認目標和范圍
整個數(shù)據(jù)庫版本升級,不是單單有標準版的主從集群,還需要考慮到中間件集群,因為NewSQL集群上線已經(jīng)完成了兼容性測試,所以不在本次升級的考慮范圍之內(nèi)。
通過這項梳理也能夠基本明確其他分支技術(shù)棧該如何做方案設(shè)計。
圖片
(二)制定升級策略
1、整體升級策略
這場數(shù)據(jù)庫版本升級的大遷徙,是從7個分支技術(shù)棧收縮為2個,所以需要對不同的分支技術(shù)棧規(guī)劃落地方案,整體上我們是傾向于讓MySQL 8.0承載盡可能完整的業(yè)務。
圖片
因為上一步明確了數(shù)據(jù)庫版本升級的范圍是標準版和中間件集群和其他分支技術(shù)棧,則需要制定相應的升級策略。
2、標準版升級策略
對于標準版主從來說,如果是MySQL 5.5,5.6版本,需要先過渡到MySQL 5.7,完成兼容性測試之后,觀察一段時間之后,再次升級到MySQL 8.0;如果是MySQL 5.7版本,則可以直接升級到MySQL 8.0。
圖片
3、中間件集群升級策略
對于中間件集群來說,整體的思路還是做拓撲下沉,即通過級聯(lián)的方式,把從庫提升為主庫。
圖片
4、其他分支技術(shù)棧升級策略
對于其他的分支技術(shù)棧來說,這些技術(shù)棧早期也確實解決了一些業(yè)務厄待解決的問題,隨著MySQL 8.0的性能提升和集群技術(shù)的迭代,需要做一些整合。
- TokuDB遷移至TiDB
- Infobright遷移至MySQL 8.0
- 對于一些歷史遺留業(yè)務,還需要研發(fā)協(xié)助完成數(shù)據(jù)旁路雙寫
所以整體來上來看,數(shù)據(jù)庫版本升級不是單一升級到8.0,在策略上需要考慮完整。
(三)定制化升級列表
如果有成百上千個實例要落地升級計劃,顯然是一件龐大的工程,某個業(yè)務有幾十個實例,斷斷續(xù)續(xù)地溝通,研發(fā)同學也受不了,而且整體的進度也不好控制,所以我們是從兩個維度來做梳理和整合的。
- 先按照數(shù)據(jù)庫版本把所有業(yè)務的信息都梳理出來,比如MySQL 5.6,MySQL 5.7的,可以整理成不同的tab頁,按照業(yè)務負責人進行匯總;
- 然后按照不同的業(yè)務大類或者業(yè)務負責人,把上面這個數(shù)據(jù)中的信息提取出來,這樣就形成了業(yè)務視角的數(shù)據(jù)庫升級計劃,基本就可以開始和研發(fā)同學溝通了;
- 當然溝通也不能全靠嘴,還需要一些標準化的文檔,比如我們整理了不同版本升級需要注意的事項,把整個過程需要研發(fā)協(xié)助的事情都列清楚,避免重復的解釋和無效溝通;
- 最后是回退方案,這應該是整個方案里面研發(fā)同學最關(guān)心的部分了,畢竟先把最壞的結(jié)果考慮到,一旦發(fā)現(xiàn)問題也能及時處理。
如下是我們計劃和研發(fā)同學進行的溝通的雙方協(xié)作的流程。
圖片
(四)研發(fā)驅(qū)動兼容性/功能測試
1、數(shù)據(jù)庫驅(qū)動兼容性測試
數(shù)據(jù)庫驅(qū)動測試是升級的一個關(guān)鍵環(huán)節(jié),而且涉及到很多開發(fā)語言,所以兼容性測試是重中之重。
為了避免走彎路,我們先期和一些研發(fā)同學一起梳理測試,整理了如下的驅(qū)動兼容性列表,這樣后續(xù)的一些研發(fā)同學接入時,就可以參考了。
圖片
而對于C++、.NET、Python、PHP、Go、NodeJS等開發(fā)語言,兼容性變動相對較小,總結(jié)如下:
圖片
除了驅(qū)動型兼容測試,對于MySQL的不同分支版本,也需要進一步測試SQL兼容性和其他注意事項。
2、MySQL 5.5,5.6升級到MySQL 8.0的兼容性測試:
1)針對group by語法、日期格式字段等有特定要求
如對于group by聚合操作,select列必須在group by中出現(xiàn),若不在group by子句中,認為不合法。示例:
mysql> select name,age from test group by name,age;
+------+------+
| name | age |
+------+------+
| aa | 18 |
+------+------+
1 row in set (0.00 sec)
mysql> select name,age from test group by name;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.test.age' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
對于group by聚合操作,order by 列必須在group by中出現(xiàn)
mysql> select name,age from test group by name,age order by name;
+------+------+
| name | age |
+------+------+
| aa | 18 |
+------+------+
1 row in set (0.00 sec)
mysql> select name,age from test group by name,age order by id;
ERROR 1055 (42000): Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'test.test.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
mysql>
- 解決方案1:研發(fā)側(cè)調(diào)整對應的SQL語句
- 解決方案2:調(diào)整MySQL5.7/8.0的sql_mode參數(shù),保證兼容MySQL5.5的語法
2)MyISAM存儲引擎的表可能存在潛在問題
解決方案:經(jīng)過排查,目前線上bbs的庫表均為innodb存儲引擎或者memory存儲引擎
3)部分SQL會出現(xiàn)執(zhí)行計劃發(fā)生改變,可能需要略微調(diào)整
解決方案:目前暫時沒有發(fā)現(xiàn),后續(xù)有類似SQL,可以針對性處理
4)字符集驗證
MySQL5.7默認字符集是utf8字符集,如果是gbk等字符集需要調(diào)整并驗證
解決方案:DBA側(cè)保證升級過后,不會出現(xiàn)亂碼等字符集報錯信息
3、MySQL 5.7升級到MySQL8.0的補充兼容性測試:
1)表中需要包含主鍵
在8.0版本中會強制要求表中包含主鍵
2)timestamp數(shù)據(jù)類型默認值
如果表結(jié)構(gòu)中有timestamp類型字段,并且設(shè)置了默認值DEFAULT CURRENT_TIMESTAMP,建議將參數(shù)設(shè)置為off:
explicit_defaults_for_timestamp=OFF(8.0默認為on)
否則有可能會出現(xiàn):Error:1048 - Column ‘createTime‘ cannot be null
3)執(zhí)行計劃變化
部分SQL會出現(xiàn)執(zhí)行計劃發(fā)生改變,可能需要略微調(diào)整
解決方案:跨版本升級中的SQL異常,可以通過提前交付只讀實例來進行預先驗證,并且抓取原庫的慢日志在8.0數(shù)據(jù)庫中進行回放驗證
4)MySQL8.0 新增關(guān)鍵字(如rank),可能導致查詢、寫入失敗
mysql> select rank from activity_public_log limit 1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from activity_public_log limit 1' at line 1
解決方案:改寫成 `rank`或者調(diào)整字段名
mysql> select `rank` from activity_public_log limit 1;
查詢方式:
select TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME from information_schema.COLUMNS where COLUMN_NAME="rank";
5)對于load權(quán)限的確認
部分業(yè)務具有導入數(shù)據(jù)的權(quán)限,在默認模板中參數(shù)secure_file_priv和local_infile是關(guān)閉的,需要和業(yè)務側(cè)確認是否有該類需求,或者從定時任務中識別
6)存儲過程權(quán)限檢查
部分業(yè)務中存在存儲過程時,對于存儲過程的權(quán)限粒度 invoker和definer差異可能導致遷移后業(yè)務調(diào)用失敗,需要在遷移中進行檢查
(五)制定資源申請和回收流程
有了前面的流程支持,整個過程基本可以跑起來了,還有一個風險則是采用資源平替的方案,也就意味著今天數(shù)據(jù)庫實例是業(yè)務A的主庫,完成升級之后我們會讓系統(tǒng)的同事重新格式化后交付給我們,很可能明天就變成業(yè)務B的從庫了,所以資源是以資源池的形式在反復利用,對于如何申請資源和下線資源就是關(guān)鍵,我們制定的流程是需要至少3次審核才可以下線,而且下線的過程中還需要有一定的觀察期窗口。
為此我們也指定了專人負責制度,即最終的下線操作只能由固定的一個人來操作,他需要對下線操作做最后的審核,并且負責。
三、版本升級問題總結(jié)
具體實施的過程還是相對順利的,為此我們也儲備了一些標準化能力,比如平臺化搭建跨版本從庫的服務,保證每個人交付的質(zhì)量是基本一致的。
所以結(jié)果整體上是預期中的,當然也發(fā)現(xiàn)了一些潛在問題,通過梳理和總結(jié),也在其他業(yè)務方向能夠參考借鑒,提高了整體服務升級的穩(wěn)定性和專業(yè)性。
圖片
版本升級的事情做完了,也盤點出了一些新的收獲:
(一)業(yè)務便于接入:通過大規(guī)模升級的過程對于多語言體系的兼容性支持做到了心中有數(shù);
(二)數(shù)據(jù)庫子版本平滑升級:后續(xù)的子版本升級演變?yōu)樵诰€升級模式,就不需要研發(fā)做額外的溝通和測試;
(三)操作系統(tǒng)無感升級:操作系統(tǒng)升級可以演變?yōu)槠交壞J剑珻entOS 7后續(xù)的版本選型和支持都可以做一些調(diào)研測試;
(四)資源治理:通過升級也發(fā)現(xiàn)有一些服務資源使用率不足需要降配,后續(xù)可以開展容量治理。
四、小結(jié)
MySQL版本升級工作,從2022年上旬開始規(guī)劃到生態(tài)完善實施了近1年,得到了多個中心研發(fā)團隊的大力支持和理解。MySQL數(shù)據(jù)庫也從原本的7個技術(shù)棧收縮為2個,挑戰(zhàn)和難度在落地時才發(fā)現(xiàn)比預期的要復雜不少,為了保證業(yè)務的穩(wěn)定性和研發(fā)工作的侵入度最低,DBA團隊也制定了完整的數(shù)據(jù)升級流程和業(yè)務切換方案,并對業(yè)務異常的回退進行了全流程準備,整個過程零故障。
后續(xù)計劃在SQL云數(shù)據(jù)庫、SQL高可用體系,SQL分布式架構(gòu)體系和SQL資源標準化四個方面持續(xù)發(fā)展,并制定相應的建設(shè)計劃。
(一)SQL資源標準化:MySQL 8.0作為基線版本,為后續(xù)的運維管理工作提供統(tǒng)一、標準的基礎(chǔ)服務支持,并對外提供一致性系統(tǒng)服務,后續(xù)提供平滑升級的平臺化方案;同時做一些資源治理,對一些使用率不足的業(yè)務可以在線降配。
(二)SQL分布式架構(gòu)體系演進:隨著水平擴展需求、信創(chuàng)、分布式事務方案的調(diào)研和業(yè)務落地演進,未來可能會基于OceanBase等國產(chǎn)化數(shù)據(jù)庫進行對比分析,適時引入;
(三)SQL高可用體系:SQL高可用體系對于標準版主從集群會基于MySQL 8.0版本作為基線,對于拓撲發(fā)現(xiàn),數(shù)據(jù)管理模式會基于新的運維命令和使用模式;
(四)SQL云數(shù)據(jù)庫服務支持:基于MySQL 8.0的服務體系會在功能和性能上面提供更加豐富,高性能的數(shù)據(jù)存儲支持,如對于JSON的格式解析和查詢等,對于SQL查詢優(yōu)化的優(yōu)化器支持等。
作者介紹
楊建榮,競技世界數(shù)據(jù)庫專家、dbaplus社群聯(lián)合發(fā)起人,騰訊云TVP,Oracle ACE,《Oracle DBA工作筆記》和《MySQL DBA工作筆記》作者;現(xiàn)就職于競技世界,擅長數(shù)據(jù)管理、數(shù)據(jù)遷移、性能優(yōu)化,目前專注于開源技術(shù)、運維自動化和性能優(yōu)化,堅持寫技術(shù)博客,已堅持2400多天。