Có và Không - như thường lệ, nó phụ thuộc. Tài liệu nói đúng rằng:
Nói cách khác, chỉ cần SELECT khác với CHỌN CẬP NHẬT / XÓA / CẬP NHẬT.
Bạn có thể tạo trường hợp kiểm thử đơn giản để quan sát hành vi đó:
Phiên 1
mạnh mẽ>
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> DELETE FROM test;
DELETE 10
test=>
Bây giờ hãy đăng nhập vào Phiên 2 khác:
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
Sau lệnh cuối cùng SELECT ... FOR UPDATE
phiên 1 "treo" và đang chờ đợi điều gì đó ......
Quay lại phiên 1
test=> insert into test select * from generate_series(1,10);
INSERT 0 10
test=> commit;
COMMIT
Và bây giờ khi bạn quay lại phiên 2, bạn sẽ thấy điều này:
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
x
---
(0 rows)
test=> select * from test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
Đó là - SELECT
đơn giản vẫn không thấy bất kỳ thay đổi nào, trong khi SELECT ... FOR UPDATE
không thấy rằng các hàng đã bị xóa. Nhưng nó không thấy các hàng mới được chèn bởi phiên 1
Trên thực tế, một chuỗi bạn đang thấy là:
- quá trình A bắt đầu giao dịch của nó
- process A xóa mọi thứ khỏi bảng T
- quá trình B bắt đầu giao dịch của nó
- tiến trình B cố gắng lựa chọn cập nhật trên một hàng trong bảng T
- quy trình B "treo" và đang đợi cho đến khi phiên A thực hiện cam kết hoặc khôi phục
- xử lý A sao chép lại bảng T từ dữ liệu đến
- process A cam kết giao dịch của mình
- quy trình B xuất hiện trống (0 hàng- sau cam kết phiên A) và lệnh gọi khôi phục