PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

org.postgresql.util.PSQLException:LỖI:không thể tuần tự hóa quyền truy cập do phụ thuộc đọc / ghi giữa các giao dịch

Bất cứ khi nào bạn yêu cầu SERIALIZABLE cô lập DB sẽ cố gắng tạo các tập hợp truy vấn đồng thời dường như đã được thực thi tuần tự xét về kết quả mà họ tạo ra. Điều này không phải lúc nào cũng có thể thực hiện được, ví dụ:khi hai giao dịch có sự phụ thuộc lẫn nhau. Trong trường hợp này, PostgreSQL sẽ hủy bỏ một trong các giao dịch với lỗi tuần tự hóa thất bại, cho bạn biết rằng bạn nên thử lại.

Mã sử ​​dụng SERIALIZABLE luôn phải chuẩn bị để thử lại các giao dịch. Nó phải kiểm tra SQLSTATE và, đối với các lỗi tuần tự hóa, hãy lặp lại giao dịch.

Xem tài liệu cách ly giao dịch .

Trong trường hợp này, tôi nghĩ rằng sự hiểu lầm chính của bạn có thể là:

vì nó không có gì thuộc loại này, nó là một INSERT ... SELECT chạm vào vo_business.repositoryoperation cho cả đọc và viết. Như vậy là đủ để tạo ra sự phụ thuộc tiềm năng với một giao dịch khác cũng thực hiện tương tự hoặc một giao dịch đọc và ghi vào bảng theo cách khác.

Ngoài ra, mã cách ly có thể nối tiếp hóa trong một số trường hợp có thể khử tạo thành thông tin phụ thuộc cấp khối giữ vì lý do hiệu quả. Vì vậy, nó có thể không nhất thiết phải là một giao dịch chạm vào các hàng giống nhau, chỉ là cùng một khối lưu trữ, đặc biệt là khi đang tải.

PostgreSQL sẽ thích hủy bỏ một giao dịch có thể tuần tự hóa nếu nó không chắc chắn rằng nó an toàn. Hệ thống chứng minh có những hạn chế. Vì vậy, cũng có thể bạn vừa tìm thấy một trường hợp đánh lừa nó.

Để biết chắc chắn, tôi cần xem cả hai giao dịch song song với nhau, nhưng đây là bằng chứng cho thấy một insert ... select có thể xung đột với bản thân của nó. Mở ba psql phiên và chạy:

session0: CREATE TABLE serialdemo(x integer, y integer);

session0: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session0: LOCK TABLE serialdemo IN ACCESS EXCLUSIVE MODE;

session1: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session2: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session1: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session2: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session0: ROLLBACK;

session1: COMMIT;

session2: COMMIT;

session1 sẽ cam kết tốt. session2 sẽ không thành công với:

ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

Đó không phải là lỗi tuần tự hóa giống như trường hợp của bạn và không chứng minh rằng của bạn các câu lệnh có thể xung đột với nhau, nhưng nó cho thấy rằng một insert ... select không phải là nguyên tử như bạn nghĩ.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách kết nối với Postgres qua Node.js

  2. Chọn hàng ngẫu nhiên

  3. Postgres / JSON - cập nhật tất cả các phần tử mảng

  4. sql - nhóm theo phạm vi để bao gồm các phạm vi không có giá trị

  5. Chèn NULL thay vì chuỗi trống với PDO