優化 RDS 碎片

之前資料庫雖然持續在刪除 log,但實際占用空間並沒有減少。問題在於 InnoDB 刪除資料後不會自動釋放空間,必須執行 OPTIMIZE TABLE 才能回收碎片。但這個操作會鎖表,而遊戲伺服器需要不停服維護,所以無法直接使用。

改用 pt-online-schema-change 進行線上遷移,整個過程不影響業務讀寫。

安裝 Percona Toolkit

sudo yum -y install https://downloads.percona.com/pub/percona/release/percona-release-latest.noarch.rpm
sudo percona-release enable tools release
sudo yum install percona-toolkit -y
pt-online-schema-change --version
# pt-online-schema-change 3.6.0

查詢各資料表碎片大小

SELECT 
    table_name,
    data_free / 1024 / 1024 AS data_free_mb
FROM information_schema.tables 
WHERE table_schema = '****_game' 
AND table_name IN (
    't_****_cards', 
    't_****_coins', 
    't_*****_credits', 
    't_****_record_one', 
    't_****_record_coin', 
    't_***_record'
);

73025-dn47yf7j4ph.png

查詢結果發現 t_****_record 碎片異常龐大,進一步確認:

SELECT 
    table_name,
    data_length / 1024 / 1024 AS data_mb,
    data_free / 1024 / 1024 AS free_mb
FROM information_schema.tables
WHERE table_schema = '****_game' AND table_name = 't_****_record';

31550-d34tjacmae.png

結果顯示實際資料約 45 GB,碎片卻高達 147 GB,碎片比資料本身還大三倍以上,非常值得清理。


執行 pt-online-schema-change

pt-online-schema-change \
  --alter="ENGINE=InnoDB" \
  --user=csmj_root \
  --password="你的密码" \
  h=rm-***********.mysql.rds.aliyuncs.com,P=3306,D=****_****,t=t_****_record \
  --chunk-size=1000 \
  --execute

一直顯示錯誤

Cannot connect to P=3024,h=,p=...,u=csmj_root: DBI connect(';host=;port=3024;mysql_read_default_group=client','csmj_root',...) failed: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) at /usr/bin/pt-online-schema-change line 2345.
Can't call method "selectrow_array" on an undefined value at /usr/bin/pt-online-schema-change line 4391.

查了 claude 跟 豆包都不行,後來查了 google AI 改成這個版本終於可以了

$ pt-online-schema-change   --alter="ENGINE=InnoDB"   --user=****_****   --password="********"   --chunk-size=1000   --recursion-method=none   --no-version-check   --execute   h=rm-uf*********.mysql.rds.aliyuncs.com,P=3306,D=nszmj_game,t=t_game_record

問題在於

  1. --recursion-method=none
    告訴 pt-osc 不要嘗試尋找備庫,跳過備庫檢查。沒加這個就會報 Can't use an undefined value as an ARRAY reference 的錯誤。
  2. DSN 放最後
    h=...,P=3306,D=...,t=... 移到指令最末尾,避免參數解析時 host 被吃掉,這是之前一直報 h= 為空的根本原因。
  3. --no-version-check
    跳過版本檢查,避免連線到 Percona 伺服器做版本驗證,在某些網路環境下會卡住。

開始進行數據遷移

17816-unv1k41gfe.png

大約執行了 20 分鐘完成

2026-04-23T03:59:14 Copied rows OK.
2026-04-23T03:59:14 Analyzing new table...
2026-04-23T03:59:14 Swapping tables...
2026-04-23T03:59:14 Swapped original and new tables OK.
2026-04-23T03:59:14 Dropping old table...
2026-04-23T03:59:15 Dropped old table nszmj_game._t_game_record_old OK.
2026-04-23T03:59:15 Dropping triggers...
2026-04-23T03:59:15 Dropped triggers OK.
Successfully altered ****_***.t_****_record.

原本使用量到了 630G,最終優化結果為 476G

72740-0yme2cb3vcx.png

碎片从 147 GB 降到 6 MB

無標籤

新增評論