先決條件
PostgreSQL
帶有彈簧資料 jpa 的彈簧啟動
問題
我有 2 張桌子。Products和ProductsLocationCounter。每個產品都有一個location_id和counter_value欄位。location_id也是 的主鍵ProductsLocationCounter。這意味著在添加新產品時ProductsLocationCounter保留按特定分組的產品數量的計數器。location_id問題是我還需要將那個時間點的計數器值附加到產品物體。
所以流程就像
1. create product
2. counter_value = get counter
3. increment counter
4. product.counter_value = counter_value
當然,這必須同時進行。現在,我已經閱讀/嘗試了不同的解決方案。
- 這個stackoverflow帖子建議我應該讓資料庫來處理并發,這對我來說聽起來不錯。但訣竅是我需要在同一事務中計數器的值。所以我創建了一個觸發器
CREATE FUNCTION maintain_location_product_count_fun() RETURNS TRIGGER AS
$$
DECLARE
counter_var BIGINT;
BEGIN
IF TG_OP IN ('INSERT') THEN
select product_location_count.counter into counter_var from product_location_count WHERE id = new.location_id FOR UPDATE;
UPDATE product_location_count SET counter = counter 1 WHERE id = new.location_id;
UPDATE products SET counter_value = counter_var WHERE location_id = new.location_id;
END IF;
RETURN NULL;
END
$$
LANGUAGE plpgsql;
CREATE TRIGGER maintain_location_product_count_trig
AFTER INSERT ON products
FOR EACH ROW
EXECUTE PROCEDURE maintain_location_product_count_fun();
并用并行流對其進行了測驗
IntStream.range(1, 5000)
.parallel()
.forEach(value -> {
executeInsideTransactionTemplate(status -> {
var location = locationRepository.findById(location.getId()).get();
return addProductWithLocation(location)
});
});
列上沒有重復counter_value。這個觸發器對多執行緒應用程式安全嗎?以前沒有使用過觸發器/postgresql 函式。不知道會發生什么
我嘗試的第二個解決方案是添加物體
PESIMISTIC_WRITE的findById方法,但即使我在帶注釋的方法中執行代碼(默認情況下為只讀錯誤),ProductsLocationCounter我最終還是得到了 。cannot execute SELECT FOR UPDATE in a read-only transaction@Transactional第三個是在同一條陳述句中更新和檢索計數器的值,但 spring jpa 不允許這樣做(也不允許底層資料庫),因為更新陳述句只回傳受影響的行數
還有其他解決方案還是我需要在觸發函式中添加一些東西以使其成為執行緒安全的?謝謝
uj5u.com熱心網友回復:
這就是我實作所需的方式。
長話短說,我使用了一個 sql 函式,并在存盤庫中呼叫了它。我不再需要觸發器了。
https://stackoverflow.com/a/74208072/3018285
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/521699.html
