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

TẠO SCHEMA NẾU KHÔNG TỒN TẠI làm tăng lỗi khóa trùng lặp

Đây là một chút rắc rối trong việc triển khai IF NOT EXISTS cho bảng và lược đồ. Về cơ bản, chúng là một nỗ lực cao cấp và PostgreSQL không xử lý các điều kiện cuộc đua một cách rõ ràng. Nó an toàn, nhưng xấu xí.

Nếu lược đồ đang được tạo đồng thời trong một phiên khác nhưng chưa được cam kết, thì nó vừa tồn tại vừa không tồn tại, tùy thuộc vào bạn là ai và giao diện của bạn. Các giao dịch khác không thể "nhìn thấy" lược đồ mới trong danh mục hệ thống bởi vì nó không được cam kết, vì vậy nó được nhập trong pg_namespace không hiển thị với các giao dịch khác. Vì vậy, CREATE SCHEMA / CREATE TABLE cố gắng tạo ra nó vì đối tượng đó không tồn tại.

Tuy nhiên, điều đó sẽ chèn một hàng vào một bảng với một ràng buộc duy nhất. Các ràng buộc duy nhất phải có thể nhìn thấy các hàng không được cam kết để hoạt động. Vì vậy, các khối chèn (dừng) cho đến khi giao dịch đầu tiên thực hiện CREATE cam kết hoặc quay trở lại. Nếu nó cam kết, giao dịch thứ hai sẽ hủy bỏ, vì nó đã cố gắng chèn một hàng vi phạm một ràng buộc duy nhất. CREATE SCHEMA không đủ thông minh để nắm bắt trường hợp này và thử lại.

Để khắc phục đúng cách PostgreSQL này có thể sẽ cần khóa vị từ, nơi nó có thể khóa tiềm năng cho một hàng . Điều này có thể được thêm vào như một phần của công việc hiện tại đang diễn ra để triển khai UPSERT .

Đối với các lệnh cụ thể này, PostgreSQL có thể thực hiện đọc bẩn của danh mục hệ thống, nơi nó có thể thấy những thay đổi chưa được cam kết. Sau đó, nó có thể đợi giao dịch không được cam kết thực hiện hoặc quay trở lại, thực hiện lại quá trình đọc bẩn để xem liệu người khác có đang đợi hay không và thử lại. Nhưng điều này sẽ có một điều kiện chạy đua trong đó người khác có thể tạo lược đồ giữa khi bạn thực hiện việc đọc để kiểm tra nó và khi bạn cố gắng tạo nó.

Vì vậy, IF NOT EXISTS các biến thể sẽ phải:

  • Kiểm tra xem lược đồ có tồn tại hay không; nếu có, hãy kết thúc mà không cần làm gì cả.
  • Cố gắng tạo bảng
  • Nếu quá trình tạo không thành công do một lỗi ràng buộc duy nhất, hãy thử lại khi bắt đầu
  • Nếu tạo bảng thành công, hãy hoàn thành

Theo như tôi biết không ai thực hiện điều đó, hoặc họ đã thử và nó không được chấp nhận. Sẽ có những vấn đề có thể xảy ra với tỷ lệ ghi ID giao dịch, v.v., với cách tiếp cận này.

Tôi nghĩ đây là một loại lỗi, nhưng đó là loại lỗi "vâng, chúng tôi biết", không phải loại lỗi "chúng tôi sẽ sửa chữa ngay". Hãy đăng lên pgsql-bug về nó; ít nhất thì tài liệu cũng nên đề cập đến cảnh báo này về IF NOT EXISTS .

Tôi không khuyên bạn nên làm DDL đồng thời như vậy.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. LỖI:không thể truy cập tệp “$ libdir / plpython2” - LỖI:không thể truy cập tệp “$ libdir / plpython3”

  2. Tạo chuỗi ngày được sử dụng trong vòng lặp for

  3. Lỗi không tìm thấy tệp PGXS Makefile khi cài đặt PostGis trên Debian

  4. Spring Data Rest:Truy vấn ngày là null ném một ngoại lệ postgres

  5. Nhận số hàng từ lệnh COPY