Trên thực tế, đây chính xác là cách Giao dịch lồng nhau được thiết kế cho. Tôi trích dẫn từ tài liệu oracle:
Vì vậy, một giao dịch con trong một giao dịch lồng nhau thông thường không có ý kiến gì về cách anh ta hoặc những đứa trẻ hoặc cha mẹ khác ( giao dịch lớn hơn ) có thể hoạt động, ngoại trừ việc thay đổi dữ liệu chung hoặc không có ngoại lệ.
Nhưng bạn có thể cấp cho anh ta ( giao dịch con ) cơ hội bỏ phiếu rất hạn chế cho số phận của anh ấy bằng cách sử dụng sub-transaction
tính năng như đã nêu tại rails tài liệu
bằng cách chuyển requires_new: true
User.transaction do
User.create(username: 'Kotori')
User.transaction(requires_new: true) do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end
Như các tài liệu nói:chỉ tạo ra 'Kotori'. vì đứa trẻ 'Nemu' mạnh mẽ đã chọn cái chết trong âm thầm.
Thêm chi tiết về Quy tắc giao dịch lồng nhau ( tài liệu về phép thuật )
Cập nhật:
Để hiểu rõ hơn tại sao rails nested transactions
hoạt động theo cách này, bạn cần biết thêm một chút về cách các giao dịch lồng nhau hoạt động ở cấp DB, tôi trích dẫn từ tài liệu api rails
:
Được rồi, tài liệu mô tả hoạt động của nested transactions
trong hai trường hợp được đề cập như sau:
Trong trường hợp lệnh gọi lồng nhau, #transaction sẽ hoạt động như sau:
-
Khối sẽ được chạy mà không cần làm gì cả. Tất cả các câu lệnh cơ sở dữ liệu xảy ra trong khối đều được nối một cách hiệu quả vào giao dịch cơ sở dữ liệu đã mở.
-
Tuy nhiên, nếu:Requi_new được đặt, khối sẽ được bao bọc trong một điểm lưu cơ sở dữ liệu hoạt động như một giao dịch phụ.
Tôi tưởng tượng cẩn thận, chỉ tưởng tượng rằng:
tùy chọn (1) ( không có request_new) có trong trường hợp bạn sử dụng DBMS hỗ trợ đầy đủ nested transactions
hoặc bạn hài lòng với hành vi "giả mạo" của nested_attributes
trong khi tùy chọn (2) là để hỗ trợ savepoint
cách giải quyết nếu bạn không.