← 所有文章

FIELD NOTES / 資料記錄與報表

資料庫交易如何讓一批紀錄一起提交或回滾

資料記錄與報表作者:站長預估 5 分鐘閱讀

以三筆批次明細示範同一交易的提交與取消,分清確定回滾、提交成功與回覆遺失後的結果不明。

本文目錄

先畫出一次提交的資料範圍

一批檢測有三筆量測,報表卻只看見兩筆,先查寫入是否逐筆自動提交。每列各自成功並不代表整批完整。本篇帶你把批次表頭與明細放入同一交易,建立全批成功才發布的流程;重點是資料庫內多筆紀錄的一致性。

先定義批次B17需要一個表頭與三筆明細,明細序號為1、2、3,數值分別10、20、30。完成狀態只有在三筆都符合規格時才可建立。批次識別、預期筆數、實際筆數與內容版本都要保存,否則只查表頭存在仍無法證明完整。

適用範圍是具有交易功能的關聯式資料庫與支援該功能的驅動程式。本文以PostgreSQL交易概念說明,不代表Q06UDVCPU或QJ71C24N可以直接執行SQL;PLC通常先交資料給有資料庫介面的上層程式,再由該程式控制連線與交易。

先在隔離測試資料庫準備批次表及明細表,對批次識別與明細序號建立適當唯一限制,並設定必要欄位和資料範圍。這些限制負責攔截不合法紀錄;交易則負責把相關更動綁成一個單位,兩者各有工作,不能互相取代。

操作前記錄現有B17資料為零,再準備可重放的輸入檔。每次測試用獨立批次識別,或依明確清理規則恢復測試環境。不要在正式生產批次上故意插入錯誤明細,也不要把正式表清空來證明回滾。

依序開始 寫入 檢查 提交

在同一資料庫連線開始交易,接著寫表頭、三筆明細與完成摘要。檢查影響筆數、明細範圍和預期筆數都符合後才提交。程式不能把表頭交給連線甲、明細交給連線乙,卻以為甲的交易可以保護乙的操作。

在PostgreSQL中,BEGIN開始交易區塊,COMMIT提交,ROLLBACK取消尚未提交的更動。實際驅動可能提供交易物件或自動開啟交易,先查自動提交設定。把這幾個字寫進紀錄文字,並不會讓驅動真的建立同一個交易。

本例成功後,另用新查詢確認表頭一筆、明細三筆、序號1到3、合計60,且狀態為完成。讀取時依批次識別限縮範圍,不以全表總筆數代替本批完整性。成功訊息要綁定B17,避免上一批完成旗標殘留。

未提交時,其他連線不應把這個未完成批次當成已完成報表。提交後何時看見新內容,還受讀取交易的快照與隔離層級影響;長時間開著的讀取交易可能仍在看舊快照。驗收應說清楚讀取端是否重新開始查詢。

交易期間避免等操作員按確認、等待PLC下一件產品或下載大型檔案。先在應用端收齊並驗證候選資料,再短時間寫入。持續開著交易會占用資源,發生鎖等待時也讓下一批更難判讀,不是等待越久就越可靠。

用第二筆失敗測試整批取消

故障演練將第二筆設為違反已建立的資料限制,例如必填欄位缺失。預期寫入失敗後,程式取消整個交易,表頭與第一筆也不留下已提交的紀錄。先看錯誤代碼,再查取消結果,不能只看畫面出現紅字。

若取消後還看見第一筆,優先查是否開著自動提交、是否切換連線,或第一筆其實屬前一次測試。保存交易識別、連線使用範圍、批次識別與步驟紀錄,才能找到資料究竟在哪一步已經被提交。

本例要求三筆不可缺一,因此不採用跳過壞列、留下其他兩列的策略。SAVEPOINT可以支援局部取消,但那是另一種業務契約。若報表必須全批一致,使用局部取消後仍提交其餘明細,就不能稱為本例的驗收成功。

PostgreSQL交易中發生錯誤後,不應假設同一交易可以照常往下寫。依驅動與錯誤狀態取消交易,再重新開始;不要捕捉例外後直接顯示成功。回滾也要有可觀察結果,連線已中斷時不能捏造伺服器確認。

練習分三輪:正常三筆應得到一加三筆;第二筆限制失敗且確認回滾後應新增零筆;開始交易後由應用主動取消也應新增零筆。每輪均另查明細與表頭,完整保存預期、實際與資料庫回覆。

提交回覆遺失時先標結果不明

最容易誤判的情況是COMMIT已送出,但網路在回覆前中斷。資料庫可能已提交,也可能尚未完成;客戶端逾時只代表沒有收到確定結果,不能直接寫成已回滾。以CommitUnknown保留待核對狀態,這是應用自訂狀態名稱。

恢復連線後,依穩定的批次識別查詢同一權威資料庫中的表頭與全部明細,核對版本、筆數與內容。若確定完整匹配,才把本次結果補記成功。查不到也要考慮舊交易是否仍在處理、查詢是否來自延遲副本,不立即換新批次識別盲目重送。

本篇只建立結果不明的核對入口,完整重送去重另需明確的識別鍵、唯一限制與衝突處理。相同鍵但內容不同應報衝突,不可把任何重複鍵錯誤都當成功。保存原候選內容,避免第二次重試讀到已變動的PLC資料。

資料庫回滾只能取消其交易保護範圍內的資料更動。已輸出的實體產品、外部郵件、另一套系統的寫入不會自動撤銷。若需要發布下游事件,可以另設可靠交付機制;不能把資料庫交易宣稱成跨設備的全域撤回。

失敗排查先分限制錯誤、連線失敗、鎖等待與結果不明。查SQLSTATE等結構化代碼比比對中文錯誤字串穩定;但不是每次斷線都會有伺服器錯誤代碼。記錄可得證據和未知項目,避免用空代碼代表沒有問題。

完成結果與常見問題

交付時應附成功及回滾查詢結果、故障注入步驟與提交回覆遺失的處置流程。這裡提供的是教學設計與預期值,尚未在使用者的資料庫或PLC實測;實際隔離層級、驅動連線池、自動提交與持久化設定仍需按部署環境驗收。

問:三筆INSERT都各自成功,就等於一個交易嗎?答:不等於。若各筆自動提交,第三筆失敗仍可能留下前兩筆。必須核對同一連線上的交易範圍與提交時機。

問:提交逾時後呼叫回滾,能保證先前資料消失嗎?答:不能。先前交易可能已提交,新連線的回滾不能取消已提交交易;先標結果不明,再依批次識別核對。

問:表頭顯示完成,就能不用查明細嗎?答:驗收不能省略。本例應看到三筆明細、序號連續且合計60;表頭完成必須與明細放在同一提交單位。

問:交易能取消PLC已執行的機械動作嗎?答:不能。資料庫原子性只涵蓋其管理的交易資料,機械動作需要獨立流程與工程驗證,不能用資料庫回滾當成機台復原。

參考:PostgreSQL 18 Transactions:交易區塊、提交、回滾及保存點。

參考:PostgreSQL 18 Error Codes:結構化SQLSTATE與連線錯誤分類。

延伸閱讀