Loại này là độ bền là không thể do ACID, với một kết nối. (nghĩa là một khối lồng nhau vẫn được cam kết trong khi khối ngoài được cuộn lại) Đây là hậu quả của ACID, không phải là vấn đề của Django. Hãy tưởng tượng một cơ sở dữ liệu siêu và trường hợp bảng B
có một khóa ngoại để bàn A
.
CREATE TABLE A (id serial primary key);
CREATE TABLE B (id serial primary key, b_id integer references A (id));
-- transaction
INSERT INTO A DEFAULT VALUES RETURNING id AS new_a_id
-- like it would be possible to create an inner transaction
INSERT INTO B (a_id) VALUES (new_a_id)
-- commit
-- rollback (= integrity problem)
Nếu giao dịch bên trong "bền" trong khi giao dịch (bên ngoài) bị cuộn lùi thì tính toàn vẹn sẽ bị hỏng. Các hoạt động rollback phải luôn luôn được thực hiện để nó không bao giờ có thể thất bại, do đó không có cơ sở dữ liệu nào sẽ thực hiện một giao dịch độc lập lồng nhau. Nó sẽ là trái với nguyên tắc nhân quả và tính toàn vẹn không thể được bảo đảm sau khi rollback chọn lọc như vậy. Nó cũng chống lại nguyên tử.
Giao dịch có liên quan đến kết nối cơ sở dữ liệu. Nếu bạn tạo hai kết nối thì hai giao dịch độc lập được tạo. Một kết nối không nhìn thấy các hàng giao dịch khác không được cam kết (có thể đặt mức cách ly này, nhưng phụ thuộc vào phần cuối cơ sở dữ liệu) và không có khóa ngoài nào được tạo và tính toàn vẹn được bảo toàn sau khi khôi phục cơ sở dữ liệu thiết kế phụ trợ.
Django hỗ trợ nhiều cơ sở dữ liệu, do đó có nhiều kết nối.
# no ATOMIC_REQUESTS should be set for "other_db" in DATABASES
@transaction.atomic # atomic for the database "default"
def my_view():
with atomic(): # or set atomic() here, for the database "default"
some_code()
with atomic("other_db"):
row = OtherModel.objects.using("other_db").create(**kwargs)
raise DatabaseError
Dữ liệu trong "other_db" vẫn được cam kết. Có thể là ở Django để tạo một thủ thuật với hai kết nối đến cùng một cơ sở dữ liệu giống như hai cơ sở dữ liệu, với một số cơ sở dữ liệu, nhưng tôi chắc chắn rằng nó chưa được kiểm tra, nó sẽ dễ mắc lỗi, với các vấn đề với việc di chuyển, tải lớn hơn bởi backend cơ sở dữ liệu phải tạo các giao dịch song song thực sự ở mọi yêu cầu và nó không thể được tối ưu hóa. Tốt hơn là nên sử dụng hai cơ sở dữ liệu thực hoặc để tổ chức lại mã.
Cài đặt DATABASE_ROUTERS rất hữu ích, nhưng tôi chưa chắc chắn liệu bạn có quan tâm đến nhiều kết nối hay không.
Tôi không thể tìm thấy câu trả lời cho câu hỏi của mình trong văn bản của bạn. Bạn nói rằng tôi cần phải đảm bảo rằng các khối nguyên tử bên ngoài được cam kết. Vâng đó là sự thật. Làm thế nào để làm điều này trong django? – guettli
@guettli Tôi đã cập nhật câu trả lời của mình. Không có API để làm điều đó, cách duy nhất để đạt được điều này là đảm bảo mã trong giao dịch kết thúc mà không có bất kỳ lỗi nào. – knbk
@guettli, nếu bạn muốn quản lý giao dịch ở cấp độ thấp trong django, bạn có thể sử dụng trực tiếp gói giao dịch 'giao dịch'. Ví dụ, bạn có thể thấy https://github.com/2ps/djenga/blob/master/djenga/db/nested_transactions.py đó là một cái gì đó tôi đã viết lại khi django không hỗ trợ các giao dịch lồng nhau trong mysql. – 2ps