expdp导出表结构_超强技术案例!86万张表迁移的优化历程
本文轉載自:華為云社區
86萬張表遷移的優化歷程問題背景:2019年12月份的時候DRS項目組接到了一個線上問題:XX客戶將mysql數據庫從友商遷移至華為云的時候性能很慢,而且出現報錯。運維同學定位發現用戶的某幾個實例存在大約2000個庫,86萬張表,而出錯的原因是查詢源庫數據庫超時。和開發同學聯系后得到了第一個解決方案:增大和源庫的socketTimeout值,保證查詢不超時。然而,運維同學在后續保障的過程中發現……01
86萬張表遷移的優化歷程
問題背景
2019年12月份的時候DRS項目組接到了一個線上問題:XX客戶將mysql數據庫從友商遷移至華為云的時候性能很慢,而且出現報錯。運維同學定位發現用戶的某幾個實例存在大約2000個庫,86萬張表,而出錯的原因是查詢源庫數據庫超時。和開發同學聯系后得到了第一個解決方案:增大和源庫的socketTimeout值,保證查詢不超時。然而,運維同學在后續保障的過程中發現超時問題得以解決但是性能無法保證,而且容易出現OOM問題。客戶要求在一天內要完成割接,然而我們目前的遷移時間遠超24個小時,由于項目的進度問題,留給DRS的時間只剩一個周末。
02
問題定位過程
問題定位
飯要一口口吃,問題也得一個個定位,回到最初的超時問題,我們首先找到了出現超時的sql語句:
SELECT?TRIGGER_NAME?FROM?information_schema.TRIGGERS?WHERE?TRIGGER_SCHEMA?=?'****';
這個sql用于查詢每個庫下面的所有觸發器(其他對象的查詢sql也有這個問題),我們發現這個sql執行了超過5分鐘,這個結果令我們很意外。因為理論上而言只查詢一個庫下面的所有觸發器,怎么會這么慢呢?explain這個sql我們發現:Extra中表示Scanned all databases!!!這意味著雖然我們只是在查詢一個庫下面的觸發器,但是其實它會掃描所有庫對應的frm文件。DEBUG了一下mysql的源碼,我們發現雖然只是查詢了一個庫下面的trigger,但是由于information_schema.triggers表里面并不是一張物理表,導致每次查詢都會去打開所有的frm文件,我們知道frm文件是用來存放mysql元數據信息的物理文件,對于用戶這個表數量,可想而知這個會對用戶的源庫IO造成多大的影響,即使有buffer pool也扛不住這么多表的緩存。更關鍵的是,用戶有2000個庫,也就是說單就查詢trigger這一個對象,我們就需要耗費2000*5=10000分鐘的時間,遷移性能可想而知。
優化思路
有了上面的結果,其實采取的優化方式很簡單了。首先,我們根據對象的類型來區分查詢所有對象的方式,對于表,我們可以使用逐庫查詢,因為查詢表的操作不會Scanned all databases;對于其他對象,我們使用只查詢一次的sql:
SELECT?TRIGGER_SCHEMA,?TRIGGER_NAME?FROM?information_schema.TRIGGERS?WHERE?TRIGGER_SCHEMA?NOT?in('mysql','information_schema','sys',?'performance_schema');
這樣我們的查詢時間大大縮短!
然而,現實是殘酷的,雖然我們縮短了從源庫查詢對象列表的時間,但是導出對象到回放對象的性能還是不夠出色,不能滿足用戶的12小時時間限制,此外偶發的OOM問題也隨之沒有解決。
03
OOM問題
問題定位
用MAT分析了heap堆存儲后發現,heap里面存在大量的DbSqlData類的對象,正是大量的這種對象導致堆內存溢出。結合我們的架構可以發現,我們在導出表結構的時候會先把所有對象結構分類型存儲在ehcache中,然后在讀取的時候又會把數據按類型導出到內存中。針對用戶的場景,我們可以計算出(用戶的表結構平均占用堆內存4000Byte)86萬張表總共需要3.44G,而我們的永久代內存只配置了2G,OOM問題可想而知。
if?[?-z?"$REPLICATOR_HEAP_SIZE"?];?then
??REPLICATOR_HEAP_SIZE="-Xms3072m?-Xmx3072m?-XX:NewRatio=3?-XX:MetaspaceSize=128m?-XX:MaxMetaspaceSize=256m"
fi
優化思路
其實這一切的問題來源都是因為我們按對象類型對ehcache進行存取,這種方式不是流式進行的,很有可能發生OOM問題。因此,解決的思路就是我們按照單個對象的粒度進行存取,并且使用內存控制的方式控制讀到堆內的對象數目,保證流式結構的回放,如何進行流式結構的回放將會在下面介紹。
04
性能問題
問題定位
為了滿足客戶的遷移時間需求,我們統計了各個階段DRS內核的工作時間,大致分為下面幾個階段:
這三個階段的執行順序是串行執行的,其中查詢對象列表花了共計1個小時,導出對象結構共計10個小時,回放共計8個小時,總計19個小時。這個結果遠遠超出了客戶的預期,為了解決這個問題,我們對整個遷移流程進行了重新梳理,發現有以下2個改進點:
1.查詢對象列表的同時可以將已查詢對象列表的結構導出2.導出對象結構可以由單線程導出演進為多線程并發導出按照上述優化流程,假定查詢對象列表時間為A,單線程導出結構所需時間為B,根據CPU核數/IO線程比我們設定導出結構的線程數為8,在源庫性能足夠的情形下,查詢對象列表+導出對象結構的時間應該等于
CostTime(hour)=max(A,?B/8)?——?約等于2
這樣我們的總時間為2 + 8 = 10小時,滿足客戶的需求!
優化思路
有了上面的分析,結合OOM問題和查詢時間優化的思路,我們有了以下的設計:
上面圖略去了數據的回放模型,主要突出了結構的回放,同時在兩個store中加入了內存控制,防止出現OOM問題。
05
優化結果
在通宵達旦的開發和驗證后,我們終于構建了以上的框架,并且成功將86萬張表的總時長優化到了10小時以內,更為可喜的是整個流程中的full gc次數為0,最終客戶的需求得以實現,技術人員也從中學習到了新的知識。
思考
優化是無止境的,其實上述的架構還存在優化空間,比如以下的兩點:
1.結構的導入和數據的回放可以并行執行,針對用戶表多數據少的場景,統計發現表結構的導入花了4個小時而數據的導入也只花了4個小時,這一個階段可以優化(DRS已經做了這個優化,會在后續的博客中給大家科普實現方式)2.結構的導出和結構回放是否可以并行執行,他們之間的限制關系是什么?如果有小伙伴對我們的架構有看法也可以積極留言,我們會去認真觀摩!
↓點擊
總結
以上是生活随笔為你收集整理的expdp导出表结构_超强技术案例!86万张表迁移的优化历程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 只取年月日 字符串_Pyt
- 下一篇: 东方卫视演得泰坦机器人_机器人“舞林大会