簡體   English   中英

循環中的 Firebird 2.5 提交/回滾(使用自主事務)

[英]Firebird 2.5 commit/rollback (using autonomous transaction) in loop

我必須在存儲過程的循環中處理記錄,例如:

create or alter procedure process_waiting_records
as
  declare   v_id                type of column my_table.id;
begin
  for
    select
      t.id
    from
      my_table t
    where
      (t.status = 'WAITING_TO_PROCESS')
    order by
      t.created_at
    into
      :v_id
  do
  begin
    execute procedure process_one_record(:v_id);
  end
end ^

問題是當process_one_record()的執行失敗(產生任何類型的異常)時,整個修改集將從調用代碼回滾。

目標是處理所有可能的記錄,如果某些記錄無法處理,我現在並不關心,這些失敗的記錄無論如何都會記錄在日志表中(使用自治事務)。

我正在考慮在一個自治事務塊中調用process_one_record()存儲過程,使用when any do (dummy code)子句。 但是,我認為這是行不通的,因為失敗的事務不會被回滾,而是被提交(參考這個主題: Firebird 2.5 自治事務中的異常處理)。

有人可以指出我如何解決這個問題的正確方向嗎?

為此,您不需要匿名交易。 當存儲過程拋出異常時,該存儲過程的影響將自動撤消。 如果存儲過程包含SUSPEND ,則只有直到最后一個SUSPEND的效果才會被撤消(將其視為保存點)。 對於任何其他形式的回滾,需要顯式回滾事務。

另請參閱 Firebird 2.5 語言參考中的保存點和 PSQL

PSQL 中不允許使用事務控制語句,因為這會破壞調用過程的語句的原子性。 但是,Firebird 確​​實支持在 PSQL 中引發和處理異常,因此可以有選擇地撤消在存儲過程和觸發器中執行的操作,而不會導致整個過程失敗。

在內部,自動保存點用於:

  • 撤消發生異常的BEGIN...END塊中的所有操作
  • 撤消過程或觸發器執行的所有操作,或者,對於可選過程,自上次 SUSPEND 以來執行的所有操作,當執行因未捕獲的錯誤或異常而提前終止時

每個 PSQL 異常處理塊也受自動系統保存點的限制。

注意: BEGIN...END塊本身不會創建自動保存點。 保存點僅在包含用於處理異常的 WHEN 語句的塊中創建。

在這種情況下,由於需要撤消單個process_one_record的影響,而不是process_waiting_records的整個處理,因此您需要允許將異常從process_one_record拋出,但要為該單個過程調用捕獲它。

簡而言之,您需要執行以下操作:

for select
  ...
do
begin
  execute procedure process_one_record(:v_id);
  when any do
  begin
    -- do nothing, last call to `process_one_record` was undone
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM