當前位置: 華文世界 > 科技

營運商核心系統國產資料庫遷移實踐

2024-02-21科技

作者介紹

陜西移動資訊科技部 張雲川

陜西移動資訊科技部 王永強

新炬網路中北三部 張建

資料庫國產化替換,全面加速資料庫國產化替換行程。以核心系統帶動周邊系統,成功在能力營運中心、CRM等核心系統中引入了國產資料庫。為確保替換工作萬無一失,我們精心制定了漸進式遷移的六步策略,確保每一步都穩健而有序,為資料庫的順利替換提供堅實保障。

一、漸進式遷移方案

第一階段:部署

目前我們主要采用了AntDB6.3.9版本,作業系統為BC Linux For Euler 21.10,為保障可用性,采用了一主兩備架構部署,其中一個副本異機房部署,避免環境因素導致的不可用。

第二階段:測試

根據套用對資料庫高效能、高並行、跨數據中心容災能力等特性要求,對目標產品進行12大類67項資料庫技術特性的多輪交叉測試。測試內容包括但不限於功能驗證、相容性測試、效能測試、壓力測試、高可用測試、擴充套件性測試、災備測試、運維管理、生態工具、安全管理等。

機器配置情況:

1. 壓力測試

在筆者的參數配置和硬體環境下測試數據如下:

測試結論:

根據測試數據分析,倉數為500倉,行程數在32-512區間,cpu、記憶體使用率與訂單處理量持續增長;行程數達到512時,tpcc orders最高達到400000,達到效能峰值;行程數512-4096時,CPU與記憶體使用率同步增長,但磁盤IO承載達到上限,可以看到tpmc orders的值持續回落伴隨CPU上下文頻繁切換,說明負載已經達到測試極限。

基於本次測試的伺服器配置及結果分析,我們推薦設定的參數值設定分享如下:

1)shared_buffers 參數

參數說明:

設定資料庫伺服器使用共享記憶體緩沖區的大小。

經驗參考:

shared_buffers設定為實體記憶體的40%,同時AntDB同樣依賴作業系統的高速緩沖區。

建議設定為shared_buffers = '200GB'

2)effective_cache_size 參數

參數說明:

最佳化器假設可以用於單個查詢的磁盤緩存的有效大小,值越大,使用索引掃描的可能性就越大;值越小,使用順序掃描的可能性就越大。

經驗參考:

  • effective_cache_size = RAM * 0.7

  • 這個參數不會影響分配給AntDB的共享記憶體,也不保留內核磁盤緩存,只是用於最佳化器的評估目的。

  • 參數effective_cache_size通知最佳化器,系統提供多大的cache,cache包括記憶體、檔案系統、cpu的cache等,是這些cache的總和。

  • 建議設定為effective_cache_size=‘400GB’

    3)max_wal_size 參數

    參數說明:

    設定2個自動checkpoint之間允許增長最大的wal日誌的大小,預設為1GB,使用方法依賴checkpoint的操作頻率,checkpoint頻率太快設定得大一些,會提升效能,但也是會消耗更多空間,同時會延長崩潰恢復所需要的時間。

    經驗參考:

  • 使用select pg_current_wal_lsn()(pg10.x版本)檢視實際的WAL位置。

  • 啟用log_checkpoints=on,然後從伺服器日誌中提取資訊(每個完成的檢查點將有詳細的統計資訊,包括WAL的數量)。

  • 建議設定為max_wal_size = '64GB'

    4)checkpoint_completion_target 參數

    參數說明:

    該參數使AntDB盡可能慢地去寫臟數據,在checkpoint_completion_target*checkpoint_timeout。

    設定的時間內,使IO操作(寫數據到磁盤)的更慢點,同時留給部份IO操作給其他任務。

    經驗參考:

    通常設定0.5-0.9之間,是防止巨大的I/O寫入,巨大的IO寫入會嚴重影響並行的查詢效能。該參數的設定,主要依賴2個條件,一個是shared_buffer的大小,另外就是磁盤的IO頻寬,IO越高該參數設定的越大。同樣100G的shared_buffer臟數據在高IO和低IO的場景下,相同的heckpoint_timeout是所設定的checkpoint_completion_target是不一樣的,高IO的設定的就大一點,低IO的就設定的小一點緩解checlpoint的時候造成的間歇性的IO波動。

    建議設定為checkpoint_completion_target = '0.9'

    5)checkpoint_timeout 參數

    參數說明:

    自動WAL檢查點之間的最長時間(預設為5分鐘),增加此參數可能會增加崩潰恢復所需的時間。

    經驗參考:

    設定該參數需要評估1分鐘產生wal日誌尺寸,在結合平均磁盤刷寫的IO速度,和磁盤每秒寫入次數。

    建議設定為checkpoint_timeout = '15min'

    6)wal_keep_size 參數

    參數說明:

    在復制環境中,保存在pg_wal目錄中wal日誌檔段的數量,以防止stadnby伺服器進行流復制所需的wal日誌被主庫刪除。

    經驗參考:

    依賴於wal日誌產生的速度和磁盤空間的大小,太大浪費空間,太小wal日誌會被刪除。

    建議設定為wal_keep_size = '512GB'

    7)max_parallel_maintenance_workers 參數

    參數說明:

    資料庫執行vacuum、create index時,能夠啟動的並列worker最大數目。

    經驗參考:

    通常設定低於8,並列worker從max_worker_processes建立的行程池中取出,數量由max_parallel_workers控制,資源限制由maintenance_work_mem控制。

    建議設定為max_parallel_maintenance_workers = '8'

    8)max_parallel_workers 參數

    參數說明:

    資料庫最大並列worker的數量,不能超過max_worker_processes的數量。

    經驗參考:

    依賴於伺服器的cpu資源,不要超過cpu的核心數的一半,盡量使的每個核心都執行一個任務,不能出現cpu資源爭搶或者排隊的情況。

    建議設定為max_parallel_workers = '128'

    9)max_parallel_workers_per_gather參數

    參數說明:

    設定單個Gather或者Gather Merge節點能夠工作的workers的最大數量。並列workers會從max_worker_processes建立的行程池中取得,數量由max_parallel_workers限制。

    經驗參考:

    預設為2,開啟大表的並列在執行計劃中就可以看到Gather或者Gather Merge的節點,同時會占用更多的資源,消耗更多的CPU資源和I/O頻寬,建議預設即可。

    建議設定為max_parallel_workers_per_gather = '2'

    10)maintenance_work_mem參數

    參數說明:

    維護性操作(例如VACUUM,CREATE INDEX和ALTER TABLE ADD FOREIGN KEY)中使用的最大的記憶體量。

    經驗參考:

  • maintenance_work_mem和該參數autovacuum_work_mem很像,沒有設定autovacuum_work_mem,預設值是-1,則使用maintenance_work_mem的設定值,maintenance_work_mem的總記憶體消耗等於maintenance_work_mem*autovacuum_max_workers。

  • 該參數為user型別的,全域設定為4GB,滿足普通的小表的維護向操作,進行大表的維護性操作,可以進行會話級別的設定,加速大表的維護性操作。

  • 該參數最好與autovacuum_work_mem分開設定,避免維護性操作與清理操作共享記憶體,降低效能。

  • 建議設定為maintenance_work_mem = '4GB'

    11)bgwriter_delay參數

    參數說明:

    將shared_buffers中的臟數據使用bgwriter行程寫入磁盤,執行「臟數據」寫入時候的延遲值。預設為200ms。即此次寫入操作執行完後等待200ms繼續下次臟數據寫入。

    經驗參考:

    控制Bgwriter行程寫入臟數據的頻率,IO效能高的設定的小一點,IO效能差的設定大一些,臟數據占用共享緩沖區也多一些。

    建議設定為bgwriter_delay = '10ms'

    12)autovacuum_max_workers參數

    參數說明:

    Autovacuum清理的最大行程數,和資料庫數目有關系,做到每個庫都有一個清理行程去工作,太少的話會在下一個周期去清理沒清理的庫,每一個autovacuum_max_workers的行程都要消耗maintenance_work_mem的值對應的記憶體大小,例如maintenance_work_mem = 64MB時,autovacuum_max_workers = 3 需要消耗64*3=192MB記憶體。autovacuum_max_workers = 4 需要消耗64*3=256MB記憶體。

    經驗參考:

    如果只有一個活躍業務db,那麽不管設定的autovacuum_max_workers多大,永遠只會啟動一個worker來對該db進行清理。如果有多個活躍業務db,單純提高autovacuum_max_workers而不提高autovacuum_vacuum_cost_limit(預設值為vacuum_cost_limit,即200)的值也沒有用。原因是autovacuum_vacuum_cost_limit對成本的限制是全域的,該參數控制了PostgreSQL例項所有worker在執行時可達到的「成本」上限,其計算公式為:autovacuum_vacuum_cost_limit/autovacuum_max_workers。一旦達到成本上限,worker就會進入休眠,sleep時間為參數vacuum_cost_delay所設定的值(然後再繼續處理)。

    建議設定為autovacuum_max_workers = '5'

    13)autovacuum_analyze_scale_factor參數

    參數說明:

    聲明在判斷是否觸發一個ANALYZE時增加到autovacuum_analyze_threshold 參數裏面的表尺寸的分數,比如100行的表垃圾數據的行數就是1行。

    經驗參考:

  • 區分小表和大表,小表使用系統級別設定就滿足需求,大表則不能依賴這樣的設定。大表需要設定單獨的表儲存參數,來進行垃圾清理,比如:

  • autovacuum_vacuum_threshold,autovacuum_vacuum_threshold (integer)

    autovacuum_vacuum_scale_factor

    autovacuum_vacuum_scale_factor

    autovacuum_analyze_threshold

    autovacuum_analyze_scale_factor

    autovacuum_vacuum_cost_delay, autovacuum_vacuum_cost_delay

    autovacuum_vacuum_cost_limit, autovacuum_vacuum_cost_limit

  • 建議多使用分區表來儲存數據,每個分區不要超過32G。

  • 業務不繁忙的時候手動進行垃圾清理或者指令碼定時任務,設定合理的表的年齡,清理長事務。

  • 建議設定為autovacuum_analyze_scale_factor = '0.01'

    14)autovacuum_analyze_threshold參數

    參數說明:

    聲明在任何表裏觸發ANALYZE所需最小的行插入、更新、刪除數量

    經驗參考:

  • 首先autovacuum是一個重IO操作。

  • 區分小表和大表,小表使用系統級別設定就滿足需求,大表則不能依賴這樣的設定。

  • 大表需要設定單獨的表儲存參數,來進行垃圾清理,比如:

  • autovacuum_analyze_threshold

    autovacuum_analyze_scale_factor

    autovacuum_vacuum_cost_delay

    autovacuum_vacuum_cost_limit

  • 經常檢視AntDB的CSV日誌,如果發現有大量的automatic analyze of table x.x.x.x,需要設定autovacuum_analyze_threshold的參數值。

  • 建議設定為autovacuum_analyze_threshold = '1000'

    15)autovacuum_naptime參數

    參數說明:

    在每次執行完一次自動清理操作後,autovacuum 行程會等待 autovacuum_naptime 指定的時間,然後再開始下一次清理操作。

    經驗參考:

  • 區分大表和小表,在小表比較多的情況下設定1-2min,在大表比較多的時候設定為5min甚至更長。

  • 經常查詢表pg_stat_progress_analyze/pg_stat_progress_vacuum,了解autovacuum的情況。

  • 建議設定為autovacuum_naptime = '1min'

    16)autovacuum_vacuum_cost_delay參數

    參數說明:

    聲明將在自動VACUUM操作裏使用的開銷延遲數值。

    經驗參考:

  • 首先autovacuum是一個重IO操作。

  • 限制清理worker在清理過程中到達最大的清理成本的時候需要將清理worker休息或者暫停一下。

  • 可以查詢pg_stat_user_tables裏面的欄位n_dead_tup,如果這個一直在增長,就需要減小該參數的暫停時間,加速清理。

  • 建議設定為autovacuum_vacuum_cost_delay = '10ms'

    17)autovacuum_vacuum_cost_limit參數

    參數說明:

    聲明將在自動VACUUM操作裏使用的開銷限制數值。

    經驗參考:

  • autovacuum所有清理worker掃描頁累計起來的成本。

  • 區分普通磁盤和固態磁盤,普通磁盤與固態磁盤在設定該參數的時候有區別,普通磁盤就2000-4000,固態磁盤可以達到20000甚至更高。

  • 可以給大表的設定的不同的儲存參數,比如autovacuum_vacuum_cost_limit。

  • 建議設定為autovacuum_vacuum_cost_limit = '4000'

    18)autovacuum_vacuum_scale_factor參數

    參數說明:

    聲明在判斷是否觸發一個VACUUM時增加到autovacuum_vacuum_threshold參數裏面的表的行數。

    經驗參考:

  • 預設值設定太小,意義對大表來說太大了,清理行數太多,容易造成瞬時IO波動。

  • 可以給大表設定的不同的儲存參數,比如autovacuum_vacuum_scale_factor。

  • 區分普通磁盤和固態磁盤,普通磁盤設定太高,清理垃圾數據多了,IO操作就加重,影響其他任務正常操作,而ssd會設定的比較高,有利於垃圾數據清理。

  • 建議設定為autovacuum_vacuum_scale_factor = '0.01'

    19)autovacuum_vacuum_threshold參數

    參數說明:

    聲明在任何表裏觸發VACUUM所需最小的行更新或刪除數量。

    經驗參考:

  • 預設值設定太小,意義對大表來說太大了,清理行數太少,容易觸發清理worker啟動,表的臟數據有變化,有觸發操作,對清理沒有意義。

  • 可以給大表的設定的不同的儲存參數,比如autovacuum_vacuum_threshold。

  • 區分普通磁盤和固態磁盤,普通磁盤設定不能擡高,ssd會設定得比較高。

  • 建議設定為autovacuum_vacuum_threshold = '1000'

    20)work_mem參數

    參數說明:

    寫到臨時磁盤檔之前被內部排序操作和哈希表使用的記憶體量。

    經驗參考:

  • 對於復雜查詢,並列執行好幾個排序或者哈希操作,每個操作都會被允許使用這個參數指定的記憶體量,然後才會開始寫數據到臨時檔。

  • explian的時候出現quicksort memory,work_mem設定正確。

  • 多個正在執行的會話進行並行的操作。被使用的總記憶體可能是work_mem值的好幾倍。

  • 建議設定為work_mem=」16MB」

    2、高可用測試

    3、業務測試

    測試環境:BigCloud Enterprise Linux For Euler 21.10 LTS,部署ESB套用進行測試

    測試結果統計資訊:

    統計業務的成功率:99.99%;及時率:15ms內,26筆超時原因為業務本身介面響應耗時長,超過該業務的介面熔斷時間導致,不影響測試結論,符合業務遷移上線條件。

    第三階段:改造

    改造的重點工作為套用的SQL程式碼語法適配改造和儲存過程改造,既要相容原資料庫的使用習慣和語法,又要考慮套用的改造成本; 透過相容性測試輸出評估報告,明確改動範圍,進行適配改造工作量評估,合理安排工作計劃。結合對映指導手冊、資料庫開發規範,完成SQL、函式、儲存過程、檢視等適配改造測試驗證工作,經業務測試確認符合要求。

    第四階段:遷移

    為了避免對原有生產業務造成影響且保證遷移數據的嚴格一致性,采用了MTK全量+DSG增量的方式,對於源資料庫集群,提前2天啟動數據遷移鏈路,在全量數據遷移之後DSG會啟動增量數據拉取模組,拉取源例項的增量更新數據並解析、封裝、儲存在本地。當全量數據遷移完成後,DSG會啟動增量日誌回放模組,從增量日誌讀取模組中獲取增量數據,經過反解析、過濾、封裝後遷移到目標例項,透過目標端主鍵保證數據的唯一性。

    第五階段:上線

    透過雙寫機制實作新老資料庫之間雙向同步,為了降低上線風險,制定了分批流量切換策略,透過F5將業務流量依次放大進行分批切換,依次進行生產套用節點升級加入、捲動替換、分流操作切換到國產資料庫中。

    在上線後原系統及雙寫仍然保留一段時間,透過雙寫實作新系統到原系統的數據單向同步,確保兩個系統數據的一致性,具備回切能力。根據業務使用反饋,平穩執行一段時間後,斷開雙寫,下線原系統。

    第六階段:監控

    我們也建設了資料庫統一運維平台,對新上線的資料庫進行統一接入。重點對資料庫執行效能進行監控,透過全面的資料庫監控以及負載分析能力確保資料庫的統一管理和最佳效能。

    目前,平台已經提供對Oracle、AntDB、GoldenDB、MySQL、GaussDB、OceanBase等多種資料庫統一管理的能力。

    AntDB資料庫主要涉及監控點:

    二、典型問題及解決辦法

    1. Merge語法不支持

    單條SQL語句以Merge關鍵字開頭插入數據的SQL語句,AntDB不支持關鍵字Merge的寫法。

    解決辦法:使用AntDB的類似語法Insert.......... on conflict do進行SQL語法覆寫。

    2.長連線占用大量記憶體不釋放

    AntDB會緩存當前會話存取過物件後設資料,如果某個會話從啟動以來,對資料庫中所有的物件都有過查詢的動作,那麽這個會話需要將所有的物件定義都緩存起來,將會占用較大的記憶體。

    解決辦法1:對於長連線,建議空閑一段時間後,自動釋放連線。同時建議提供SQL語法給使用者,允許使用者自主的釋放cache。

    解決辦法2:最佳化relcache的管理,為relcache等緩存提供LRU管理機制,限制總的大小,淘汰不經常存取的物件。

    3.buff/cache的占用率高

    在作業系統層面使用free -g看到buff/cache占用很高,由於參數effective_cache_size設定偏高,導致占用系統記憶體偏高,對參數effective_cache_size進行調小設定。

    解決辦法:設定為記憶體的1/2是比較保守的設定,設定為記憶體的3/4是推薦的值。

    4.Mtk程式出現org.pjdbc.JdbcSQLTimeoutException: Timeout trying to lock table{0}

    源端Oracle表數目過多,Mtk在掃描表時遲遲無法掃描結束,導致其他Mtk行程有存取該表造成死結;Mtk在遍歷Oracle表名時,由於表的數目偏多,在Mtk原始碼中關於遍歷表的列表或者hash偏小導致的。

    解決辦法:使用更快的Mtk(antcdc-db-sync.tar)掃描包替換原有Mtk包,重新開機服務,執行透過。

    5.單機多例項的mtk安裝問題

    安裝在不同使用者下面存在/tmp/vertx-cache許可權拒絕問題,不能臨時修改該檔許可權。

    解決辦法:在啟動的時候不需要啟動kafkasql行程(僅適用於全量遷移)。

    6.ERROR:INVALID byte sequence for encoding ""UTF8"": 0X00

    Oracle 和 MySQL 支持儲存(0x00)字元,但是AntDB-T會報ERROR: invalid byte sequence for encoding."UTF8":0x00..

    解決辦法1:AntDB-T 欄位型別改為bytea,需要業務側考慮影響。

    解決辦法2:AntDB-MTK支持使用replaceAll將0x00 即\u0000替換為空字串,需要在配置檔config/application.properties新增或調整為replace.zero.char=true,重新開機管理工具使配置生效,任務需要重新配置。

    7.Mtk在建立數據遷移時出現錯誤Ora-00942

    在對Oracle 19.7非pdb模式下,使用Antdb Mtk遷移數據時,觸發Ora-00942錯誤,錯誤資訊為表或者檢視不存在。

    Mtk在對Oracle數據遷移時會對Oracle的一些字典表授權進行查詢,比如ALL_TABLES 、ALL_CONSTRAINTS 、ALL_MVIEWS、ALL_VIEWS、ALL_USERS....,但是在19c非pdb版本中,MTK工具目前對許可權的管控還有進一步最佳化提升的地方,使用原有字典表刷許可權的方法不能解決該場景問題。

    解決辦法1:授權dba許可權,但許可權過大,不符合生產許可權管理辦法。定為臨時解決方案。

    解決辦法2:協調廠商及時修復,輸出最小化許可權列表。

    8.Pip3 list出現no moudle pip._internal問題

    在部署AntDB的高可用元件Etcd和Patroni之後,會使用pip/pip3 list來檢查所安裝python安裝包,在執行pip3 list的時候出現no moudle pip._internal。

    在主機伺服器入網時,需進行安全基線掃描,其中包含「在/etc/profile 檔尾存在umask 027則合規,否則不合規」。

    系統之後建立檔是會有一個預設許可權,那麽這個許可權是怎麽來的呢?這就是umask幹的事情。umask用於設定使用者建立檔或者目錄的預設許可權,umask設定的是許可權的「補碼」,而我們常用chmod設定的是檔許可權碼。

    解決辦法:在進行安全基線配置的時候著重註意該條目,保證檔和目錄的許可權不發生變化。

    三、總結

    目前國產資料庫已在多個業務系統上線使用,經過紮實準備和測試驗證,遷移過程無一例回切,上線後經受住了業務環節的嚴苛考驗,滿足核心生產要求,更加堅定了我們繼續前進的信心。另外,我們也透過遷移實踐積累了寶貴的資料庫替換經驗,形成了一套完整且系統化的改造方案,為後續其他業務系統遷移奠定了基礎。