觀點 · 資訊分享
Aurora DSQL 終於支援外鍵:資料表之間的關聯交給資料庫把關,程式少寫一層檢查
AWS 的分散式資料庫 Aurora DSQL 開始支援外鍵限制,新舊資料表都能加。訂單指到不存在的商品這種髒資料,資料庫會直接擋下來,但寫入衝突時要記得重試。
- 發布
- 2026-08-27
- 篇幅
- 約 4 分鐘 · 1,825 字
- 結構
- 7 節 + 4 題常見問題
- 標籤

一句話看懂:AWS 的分散式資料庫 Aurora DSQL 開始支援外鍵,資料表之間的關聯可以交給資料庫把關,不用再全靠程式碼自己檢查。

先用白話講:外鍵是什麼?
想像一間餐廳的點餐單。每張點餐單上都會寫「點了幾號餐」,而菜單上一定要真的有這個號碼,不然廚房會一頭霧水。
外鍵(Foreign Key)就是資料庫裡的這條規則:訂單表裡的「商品編號」,必須在商品表裡找得到。有了它,資料庫會主動擋下兩種錯誤:
- 新增一張訂單,卻指到根本不存在的商品
- 把商品刪掉,卻還有訂單指著它(這種被遺留的資料叫「孤兒資料」)
一般的 PostgreSQL、MySQL 早就有外鍵,但 AWS 的 Aurora DSQL 是另一種設計:它把資料分散在多個區域同時讀寫,在這次更新之前並不提供外鍵,開發者只能在程式裡自己檢查。
發生什麼事
AWS 在 8 月 27 日宣布,Aurora DSQL 現在可以替新建和既有的資料表加上外鍵限制,所有提供 DSQL 的區域都能用。
- 支援 5 種「被指向的資料刪除或修改時怎麼辦」的動作:NO ACTION、RESTRICT、CASCADE、SET NULL、SET DEFAULT
- 支援 2 種比對方式:MATCH FULL 和 MATCH SIMPLE(預設)
- 也支援可延後到交易結束才檢查的外鍵(DEFERRABLE)
跟一般資料庫有什麼不一樣?
一般資料庫檢查外鍵時會「上鎖」,別人要改同一筆資料就得排隊。DSQL 不這樣做,而是分兩步:
| 步驟 | 做法 | 白話 |
|---|---|---|
| 交易進行中 | 用交易開始那一刻的快照確認關聯成立 | 先照當下的菜單核對 |
| 提交時 | 檢查期間有沒有人改到被指向的資料 | 送單前再確認菜單沒被改 |
好處是大家可以同時寫入、不用排隊;代價是衝突不會等待,而是直接失敗。例如 A 刪掉商品、B 同時新增指向它的訂單,先提交的 A 會成功,B 提交時就會收到錯誤。
給開發者的技術細節
語法和 PostgreSQL 相同,可以寫在欄位後面,也可以寫成資料表限制:
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_id integer REFERENCES products ON DELETE RESTRICT,
quantity integer
);
- 沒寫被指向的欄位時,預設指向對方的主鍵
- 衝突時會回
SQLSTATE 40001(序列化錯誤),一定要寫重試邏輯 - 官方文件提醒:所有動到相關資料表的寫入都會多出讀取,加之前先壓測
- 被大量參照的那一列,被參照的欄位最好不要常改;常變動的值放在其他欄位,就不會跟新增訂單互相衝突
我的看法
接案做系統時,資料表之間的關聯是最容易出包的地方:程式某條路徑忘了檢查,資料庫裡就多一筆孤兒資料,等到報表對不起來才發現。能把這層交給資料庫,是很實在的進步,也讓既有的 PostgreSQL 專案搬到 DSQL 少一個改寫的理由。
不過要記得 DSQL 的個性:它選擇「衝突就失敗」而不是「排隊等」。習慣傳統資料庫的人如果沒寫重試,流量一高就會看到一堆莫名其妙的錯誤。我的建議是先在重試機制完整的服務上加外鍵,再慢慢擴大。
名詞小辭典
- 外鍵(Foreign Key):規定某個欄位的值,必須在另一張表裡找得到,用來維持資料之間的關聯正確。
- 孤兒資料:指向的資料已經不存在,卻還留在資料庫裡的紀錄。
- 交易(Transaction):一組要嘛全部成功、要嘛全部取消的資料庫操作。
- 快照(Snapshot):交易開始那一刻整個資料庫的樣子,交易進行中都以它為準。