2013-02-18 54 views
1

我們有一個過程,它彙總一些數據並將結果插入另一個表中,我們用它來進行高效的查詢。我們面臨的問題是,我們現在有多個聚合器大致同時運行。如何插入,同時避免與oracle的唯一約束

我們使用原始記錄ID作爲此新表中的主鍵 - 唯一的約束。但是,如果兩個聚合進程同時運行,其中一個進程會因爲唯一的約束違例而出錯。

有沒有辦法指定某種鎖定機制,這將使第二個寫入器等到第一個完成?或者,有沒有辦法告訴oracle忽略該特定的行並繼續其餘的?

不幸的是,將聚合減少到單個進程是不現實的,因爲以下過程依賴於可用數據的最新版本,並且這些過程需要向外擴展。

編輯:

下面是我的[絕密]查詢:

INSERT INTO 
agg_table 
SELECT 
h.id, h.col, h.col2 
FROM history h 
JOIN call c 
ON c.callid = h.callid 
WHERE 
h.id > (SELECT coalesce(max(id),0) FROM agg_table) 
+0

您是否考慮過使用語句級並行機制而不是同時運行多個語句? – 2013-02-18 05:42:56

+0

現在您已經添加了查詢,但我不明白您在同一時間運行其中兩個時所獲得的收益。也許你應該找出哪個id需要在一個select中做,然後爲特定的非重疊範圍發出並行SQL語句。 – 2013-02-18 06:10:11

+0

@WW。通過並行運行該聲明無法獲得任何結果。但是運行sql的過程需要平行,並且需要儘可能新的數據來完成工作。 – 2013-02-18 06:25:28

回答

2

有可能運行一個INSERT語句錯誤日誌條款。從Oracle文檔的例子如下:

INSERT INTO dw_empl 
    SELECT employee_id, first_name, last_name, hire_date, salary, department_id 
    FROM employees 
    WHERE hire_date > sysdate - 7 
    LOG ERRORS INTO err_empl ('daily_load') REJECT LIMIT 25 

或者,你可以嘗試使用[MERGE][2]聲明。您將通過詳細信息表中的選擇合併到彙總表中。如果找不到匹配項,您INSERT,如果找到,您將UPDATE。我相信這個解決方案會處理你的併發問題,但你需要測試它。

+0

是的,閱讀如何使用合併的時間我認爲。感謝指針。 – 2013-02-18 05:39:44

+0

MERGE沒有幫助,我假設因爲交易時間太長。你的LOG ERRORS解決方案是否忘記了這些咒語並丟棄它們? – 2013-02-18 07:01:22

+0

是的,它會將錯誤放在另一個表中 – 2013-02-18 20:30:27

0

看看FOR UPDATE條款。如果您在更新/插入語句之前正確地在事務中使用FOR UPDATE子句寫入SELECT語句,您將能夠「鎖定」所需的記錄

0

將插入序列化可能是最好的方法,因爲沒有方法可以讓你圍繞多個插入的問題無法看到每個人在做什麼。

DBMS_Lock可能是適當的序列化機制。