剛進公司,主管叫你改一筆正式站的資料,你是不是想說「不就下個 UPDATE 嗎?」
等等,先別急。
正式站(Production)的資料是公司的命根子。改錯一筆訂單金額,可能讓財務對帳對到哭;漏了 WHERE 條件,整張表的資料可能就飛了。
這篇文章用最白話的方式,告訴你正式站資料變更的眉角,讓你不會踩雷、不會背鍋。
先搞懂為什麼不能亂改
正式站資料 = 公司的錢
想像一下:
- 客戶的訂單紀錄 → 搞丟了,客戶來吵,客服崩潰
- 付款紀錄 → 改錯了,財務對不上帳,老闆臉綠
- 會員資料 → 刪掉了,違反個資法,公司被罰錢
重點:正式站的資料不是你的練習場,每一筆都是真金白銀。
手動改資料的常見悲劇
| 悲劇類型 | 怎麼發生的 | 下場 |
|---|---|---|
| 忘了加 WHERE | UPDATE orders SET status = 'cancelled' 結果整張表都被取消 | 全公司訂單消失 |
| 連錯資料庫 | 以為連的是測試機,結果是正式機 | 測試資料蓋掉真實資料 |
| 手殘打錯字 | amount = 100 打成 amount = 1000 | 客戶多付十倍錢 |
| 沒備份就改 | 改完才發現改錯,想回復但沒備份 | 只能跪著道歉 |
出事了,誰要負責?
如果沒有留紀錄,出事就會變成:
- 「誰改的?」「不是我」「也不是我」
- 「什麼時候改的?」「不知道」
- 「改了什麼?」「忘了」
最後變成互相指責,團隊氣氛超差。
所以:每次改資料都要有紀錄,寫清楚誰改的、為什麼改、改了什麼。
正確的改法(SOP)
核心概念很簡單:改資料也要像寫程式一樣,寫 Migration、發 PR、讓人審核。
完整流程一覽
提需求 → 寫 Migration → 發 PR → 找人審 → 測試環境跑跑看 → 正式執行 → 確認結果聽起來很麻煩?但這能救你一命。
步驟拆解
先提需求
不要自己偷偷改,先開一張單(Jira、Notion 都行),寫清楚:
【我要改什麼】
訂單 #12345 的金額從 1000 改成 1100
【為什麼要改】
客戶反應金額算錯,已確認是 Bug 造成
【影響範圍】
就這一筆訂單
【什麼時候改】
今天晚上 10 點(人少的時候)寫成 Migration
Migration 是什麼?
簡單說,Migration 就是「把資料庫變更寫成腳本檔案,用 Git 管理」。
就像程式碼有版本紀錄,資料庫的變更也應該有。這樣:
- 每個環境(開發、測試、正式)跑同一套腳本,不會有「我的可以跑,你的不行」
- 所有變更歷史都查得到
- 可以搭配自動化部署
放在哪裡?
專案裡通常會有一個專門放 Migration 的資料夾:
/database/migrations/
├── 001_create_users.sql
├── 002_add_email_column.sql
├── 003_fix_order_12345_amount.sql ← 你的資料修正放這裡怎麼寫?
Migration 通常有兩個部分:
| 部分 | 用途 |
|---|---|
| up | 執行變更(往前走) |
| down | 復原變更(往回走) |
結構變更(DDL)的 up/down
結構變更很直觀,做什麼就反過來:
-- UP
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- DOWN
ALTER TABLE users DROP COLUMN phone;資料變更(DML)的 up/down
資料變更比較麻煩,因為你要先知道「原本的值是什麼」才能還原。
單筆資料:直接寫死原值就好
-- Migration: 003_fix_order_12345_amount.sql
-- 變更單號:CHG-001
-- 目的:修正訂單金額(1000 → 1100)
-- 申請人:小明
-- 日期:2024/12/01
-- ========== UP ==========
UPDATE orders
SET amount = 1100
WHERE order_id = 12345;
-- ========== DOWN ==========
UPDATE orders
SET amount = 1000
WHERE order_id = 12345;就這樣,不用為了一筆資料建備份表。
批次變更:才需要考慮備份
如果是改幾百、幾千筆,而且每筆原值都不同,這時候才需要備份表或在執行前做資料庫快照。
業界更常見的做法:Fix Forward
老實說,很多團隊根本不寫 down,而是採用 Fix Forward(向前修復):
- 發現問題 → 不回滾,直接發一個新的 migration 來修正
- 好處:不用煩惱 down 怎麼寫,也不會丟失中間產生的新資料
- 這是 DevOps 團隊越來越主流的做法
資料變更寫 down 的限制
| 情況 | 能不能 down |
|---|---|
| 改一筆已知的值 | ✅ 直接寫死原值 |
| 批次更新(每筆原值不同) | ⚠️ 要靠備份或快照 |
| DELETE 刪掉資料 | ⚠️ 一定要有備份 |
| INSERT 新增資料 | ✅ down 就是 DELETE |
| 資料已經被其他程式改過 | ❌ 回不去了,用 Fix Forward |
重點:單筆改值直接寫死就好,批次變更才需要備份策略。
常見的 Migration 工具
| 工具 | 適合誰 |
|---|---|
| Flyway | 通用,寫純 SQL 就好 |
| Liquibase | 通用,支援多種格式 |
| Knex.js | Node.js 專案 |
| Laravel Migrations | PHP Laravel 專案 |
發 PR,找人審
把 Migration 檔案 commit 到 Git,開 Pull Request。
為什麼要發 PR?
- 有版本紀錄,之後查得到
- 讓別人幫你看有沒有寫錯
- 跟改程式碼一樣的流程,大家都熟悉
審核重點
- WHERE 條件有沒有寫對?會不會改到不該改的?
- 有沒有先備份?
- 回復的 SQL 準備好了嗎?
先在測試環境跑
PR 過了之後,先在測試機跑一次,確定沒問題。
測試完要確認
- 影響的筆數對不對?(應該是 1 筆,不是 1000 筆)
- 改完的結果對不對?
- 回復的 SQL 能不能正常運作?
正式執行
選在人少的時候(比如晚上 10 點),然後:
- 先做完整備份
- 執行 Migration
- 確認結果
- 把執行過程記錄下來
回報結果
改完之後,回到需求單寫上:
【執行結果】
✅ 成功
執行時間:2024/12/01 22:05
影響筆數:1 筆
備份位置:orders_backup_001新手常見問題
改一筆資料也要這麼麻煩嗎?
看情況。可以分等級:
| 風險 | 情況 | 怎麼處理 |
|---|---|---|
| 低 | 改 1-10 筆,不是錢相關 | 找個人幫你看一下就好 |
| 中 | 改 10-1000 筆 | 完整流程,要先在測試環境跑 |
| 高 | 改超多筆,或是金流/個資相關 | 完整流程 + 主管審核 + 離峰執行 |
很急怎麼辦?來不及走流程
- 至少找一個人(主管或資深同事)口頭確認
- 全程錄影或截圖
- 事後 24 小時內把文件補齊
- 開檢討會,看看怎麼避免下次又這麼趕
公司根本沒這些流程,我一個人能做什麼?
慢慢來,可以這樣開始:
- 先做:把你的 SQL 都存成檔案,放進 Git
- 再推:找同事互相看 SQL,養成發 PR 的習慣
- 然後:建議主管建立測試環境
- 最後:導入 Migration 工具,讓流程自動化
總結:三個字
別。手。改。
把資料變更當程式碼管理,遵守這個流程:
寫 Migration → 發 PR → 找人看 → 先測試 → 再正式改 → 留紀錄這樣就算出事,你也有紀錄證明自己照 SOP 做了,不會變成背鍋俠。
快速檢查表
改正式站之前,確認這些有沒有做:
- [ ] 有開需求單
- [ ] Migration 寫好了
- [ ] PR 發了,有人審過
- [ ] 測試環境跑過了
- [ ] 有準備回復的 SQL
- [ ] 有先備份
- [ ] 選在人少的時候改
- [ ] 改完有回報結果
全部打勾再動手,保你平安。
記住:正式站不是你的沙盒,每一次操作都要當成在拆炸彈。