不是每件工作都需要整個資料庫。當你在本機開發某個功能時,你很少會想要一份把磁碟塞滿、又要花一小時才匯入完的完整正式環境 dump。你要的只是這個功能實際會用到的那幾個資料表。
當你在除錯單一資料表時也是如此——要重現 orders 裡的某個資料問題,並不需要另外那 126 個資料表——或者在做部分遷移、只把少數幾個資料表搬到新服務時也一樣。在所有這些情況下,問題都相同:我該怎麼從一個龐大的 dump 裡,乾淨又快速地取出就這幾個資料表?
sed/grep 的做法,以及它為何會出錯
經典的解法是用 sed,在 mysqldump 為每個資料表寫入的區段標頭之間切出檔案:
# 從 mysqldump 檔案中取出 users 資料表
sed -n '/-- Table structure for table `users`/,/-- Table structure for table/p' dump.sql > users.sql
看起來很聰明,在一個小巧整齊的 dump 上甚至可能成功一次。但在真實的 7 GB 檔案上,它會以許多不易察覺的方式崩解:
- 多行 INSERT。單一個
INSERT INTO ... VALUES可能橫跨數千行。sed、grep這類以行為單位的工具會把這些資料列從中切斷,產出一個無法解析的檔案。 - 反引號與特殊字元。欄位值裡含有
--、分號、反引號、引號,以及字串內的換行。你的樣式會比對到資料內部那些原本不該當作分隔符的文字。 - 資料表名稱作為子字串。抽取
user也會一併抓到user_roles、user_sessions和password_user,因為這個名稱剛好是其他名稱的子字串。 - 註解與標頭會飄移。精確的註解文字在 MySQL、MariaDB 與 PostgreSQL 各版本之間都不一樣,而
pg_dump根本不用同一套標頭——所以同一道指令會悄悄地什麼都沒回傳。 - 不懂外鍵。就算你把
orders完美切出來,它的資料列仍會參照users。sed對此毫無概念,於是抽取出來的檔案匯入時會出現外鍵錯誤。
你最後把 awk 疊到 grep 上、再疊到 sed 上,在小樣本上反覆測試,卻仍然不敢相信結果。其實有更好的方法。
用 DumpCleaner 抽取資料表
DumpCleaner 會正確地解析 dump——它理解陳述式邊界、多行 INSERT、反引號與註解——所以它總是切在正確的位置。抽出你需要的資料表只需四個步驟:
- 把你的
.sqldump 拖進來。DumpCleaner 串流讀取檔案,所以一個 7 GB 的 dump 是以恆定記憶體開啟,而不是把整個檔案載入。 - 看自動偵測出來的資料表清單。每個資料表都會被解析出來,並列出其資料列數與大小——不必在數百萬行裡捲來捲去找東西。
- 挑選你要的資料表。勾選
users、orders和products,或輸入正規表示式/排除樣式(例如*_logs)來一次去掉整組資料表。 - 納入外鍵父表並匯出。可選擇自動帶入被參照的父表,然後匯出一份乾淨、可匯入的檔案。
有幾點讓這件事比 shell 工具省事許多:
- 排除樣式(例如
*_logs或*_sessions)可濾掉稽核與 session 雜訊,不必手動一個個取消勾選幾十個資料表。 - 正規表示式過濾讓你依前綴、後綴或任意樣式比對——例如保留所有符合
shop_*的資料表。 - 即時預覽會在你變更選取時,準確顯示哪些資料表最終會出現在輸出中。
- 預估輸出大小會在你匯出前告訴你抽取結果會有多大,讓你知道它塞得進本機。
- 外鍵相依關係可自動納入,所以選了
orders就會悄悄把users一起帶上,抽取結果匯入時不會出現約束錯誤。
只要你需要的資料表——其他一概不要
DumpCleaner 能從任何大小的 dump 中抽取特定資料表——採串流處理、記憶體恆定,並替你解析好外鍵。原生 macOS & iPadOS App,一次性買斷。
在 App Store 下載常見問題
我可以一次抽取多個資料表嗎?
可以。想勾幾個就勾幾個——users、orders 和 products 一起——DumpCleaner 會在一趟處理中把它們全部寫進同一個檔案。
它會保留外鍵相依關係嗎?
可選擇保留。開啟納入外鍵相依關係,凡是你選取的資料表所參照的父表都會被自動帶入,所以抽取結果匯入時不會出現約束錯誤。
我可以依樣式排除資料表嗎?
可以。使用像 *_logs 或 *_sessions 這類排除樣式,或用正規表示式,就能一次去掉整組資料表,不必一個個取消勾選。
它能搭配 PostgreSQL 使用嗎?
可以。DumpCleaner 能讀取 MySQL、MariaDB 與 PostgreSQL(pg_dump)dump,並在抽取資料表時處理像 public.users 這樣帶結構描述前綴的名稱。