Hành vi bạn mô tả là bình thường và được mong đợi trong bất kỳ cơ sở dữ liệu quan hệ giao dịch nào.
Nếu PostgreSQL hiển thị cho bạn giá trị edited
cho SELECT
đầu tiên sẽ là sai khi làm như vậy - đó được gọi là "đọc bẩn" và là tin xấu trong cơ sở dữ liệu.
PostgreSQL sẽ được phép đợi tại SELECT
cho đến khi bạn cam kết hoặc quay trở lại, nhưng nó không bắt buộc theo tiêu chuẩn SQL, bạn đã không nói với nó rằng bạn muốn đợi và nó không phải đợi vì bất kỳ lý do kỹ thuật nào, vì vậy nó sẽ trả về dữ liệu bạn đã yêu cầu cho ngay lập tức. Rốt cuộc, cho đến khi nó được cam kết, update
đó chỉ loại tồn tại - nó vẫn có thể xảy ra hoặc có thể không xảy ra.
Nếu PostgreSQL luôn đợi ở đây, thì bạn sẽ nhanh chóng gặp phải tình huống chỉ có một kết nối có thể làm bất cứ điều gì với cơ sở dữ liệu tại một thời điểm. Không đẹp cho hiệu suất và hoàn toàn không cần thiết trong phần lớn thời gian.
Nếu bạn muốn đợi UPDATE
đồng thời (hoặc DELETE
), bạn sẽ sử dụng SELECT ... FOR SHARE
. (Nhưng lưu ý rằng điều này sẽ không hoạt động đối với INSERT
).
Chi tiết:
SELECT
không có FOR UPDATE
hoặc FOR SHARE
mệnh đề không có bất kỳ khóa cấp độ hàng nào. Vì vậy, nó nhìn thấy bất cứ điều gì là hàng được cam kết hiện tại và không bị ảnh hưởng bởi bất kỳ giao dịch trong chuyến bay nào có thể đang sửa đổi hàng đó. Các khái niệm được giải thích trong phần MVCC của tài liệu
. Ý tưởng chung là PostgreSQL là copy-on-write, với cách lập phiên bản cho phép nó trả lại bản sao chính xác dựa trên những gì giao dịch hoặc câu lệnh có thể "nhìn thấy" tại thời điểm nó bắt đầu - cái mà PostgreSQL gọi là "snapshot".
Trong READ COMMITTED
mặc định ảnh chụp nhanh cách ly được thực hiện ở cấp câu lệnh, vì vậy nếu bạn SELECT
một hàng, COMMIT
một thay đổi đối với nó từ một giao dịch khác và SELECT
nó một lần nữa, bạn sẽ thấy các giá trị khác nhau ngay cả trong một lần chuyển đổi. Bạn có thể sử dụng SNAPSHOT
cô lập nếu bạn không muốn thấy các thay đổi được cam kết sau khi giao dịch bắt đầu hoặc SERIALIZABLE
cô lập để tăng cường bảo vệ chống lại một số loại phụ thuộc giữa các giao dịch.
Xem chương cách ly giao dịch trong tài liệu .
Nếu bạn muốn một SELECT
để đợi các giao dịch đang tiến hành cam kết hoặc khôi phục các thay đổi đối với các hàng đang được chọn, bạn phải sử dụng SELECT ... FOR SHARE
. Điều này sẽ chặn trên ổ khóa được thực hiện bởi một UPDATE
hoặc DELETE
cho đến khi giao dịch đã khóa trở lại hoặc cam kết.
INSERT
thì khác, tuy nhiên - các bộ giá trị không tồn tại đối với các giao dịch khác cho đến khi cam kết. Cách duy nhất để đợi INSERT
đồng thời s là lấy một EXCLUSIVE
khóa cấp bảng, vì vậy bạn biết không ai khác đang thay đổi bảng trong khi bạn đọc nó. Thông thường, việc cần làm đó có nghĩa là bạn gặp sự cố thiết kế trong ứng dụng - ứng dụng của bạn không nên quan tâm nếu có insert
chưa cam kết vẫn đang bay.
Xem chương khóa rõ ràng của tài liệu .