2013-06-06 27 views
5

Tôi đã đọc trên các mức cách ly giao dịch khác nhau và xuất hiện trên mức cách ly SERIALIZABLE. Tôi cũng biết rằng các cơ sở dữ liệu như Postgres, Oracle và MySQL hỗ trợ cú pháp SELECT .. FOR UPDATE.Giao dịch có thể thực hiện được so với CHỌN ĐỂ CẬP NHẬT

Tuy nhiên, tôi đã nhầm lẫn về cách sử dụng chúng khi tôi muốn khóa một hàng (hoặc một loạt hàng) mà tôi muốn thực hiện cập nhật.

Khi sử dụng JPA trong quá khứ, tôi luôn sử dụng @Transactional kết hợp với một LockModeType.PESSIMISTIC_WRITE trên truy vấn. Điều này chuyển sang sử dụng mức cách ly READ_COMMITTED với một số SELECT .. FOR UPDATE trong SQL.

Nhưng bây giờ, sau khi đọc về SERIALIZABLE, tôi đang tự hỏi điều gì sẽ khác nếu tôi sử dụng @Transactional(isolation=SERIALIZABLE) với một bình thường SELECT (ví dụ em.findById để lấy một thực thể tách rời), tiếp theo là một UPDATE (hợp nhất của thực thể).

Hành vi có giống nhau không?

Ví dụ: tôi có hệ thống Ngân hàng và tôi muốn chuyển tiền giữa hai tài khoản. Tôi yêu cầu các tài khoản này không được can thiệp vào, trong khi quá trình chuyển đang diễn ra. Vì vậy, giả sử tôi ghi nợ một tài khoản với -100 và ghi có vào tài khoản khác. Điều gì sẽ là cách tốt nhất để đảm bảo rằng các tài khoản này chỉ có sẵn cho giao dịch thực hiện cập nhật?

Giả sử rằng tôi đang điều khiển các thực thể tách rời JPA, vì vậy trước khi cập nhật, tôi sẽ phải đọc chúng từ DB, ví dụ: findById().

  • Sử dụng @Transactional(isolation=READ_COMMITTED), em.findById với LockModeType.PESSIMISTIC_WRITE (ví dụ: SELECT .. FOR UPDATE), và sau đó em.merge (ví dụ: UPDATE)?
  • HOẶC Sử dụng @Transactional(isolation=SERIALIZABLE), em.findById, và sau đó em.merge (ví dụ: UPDATE)?

Trả lời

2

Sự khác biệt chính giữa SERIALIZABLE và sử dụng SELECT FOR UPDATE là với tất cả mọi thứ SERIALIZABLE luôn bị khóa. Ở đâu như với SELECT FOR UPDATE bạn có thể chọn những gì và khi bạn khóa. Vì vậy, nếu bạn chỉ muốn khóa một số dữ liệu, tức là BankAccount nhưng không phải là khác, tức là Branch, AccountTypes, thì SELECT FOR UPDATE cho phép bạn kiểm soát tốt hơn, nơi SERIALIZABLE sẽ chặn toàn bộ hệ thống của bạn bởi vì mỗi giao dịch được chọn từ ACCOUNT_TYPES bàn. Ngoài ra, một số giao dịch có thể chỉ muốn kiểm tra số dư, do đó, không cần phải khóa bảng TÀI KHOẢN.

Xem,

http://en.wikibooks.org/wiki/Java_Persistence/Locking

+6

"* với tất cả mọi thứ SERIALIZABLE luôn bị khóa *" không đúng như một tuyên bố chung. Điều này phụ thuộc rất nhiều vào việc thực hiện DBMS (Postgres ví dụ không làm điều đó) –

+0

Đó là sự thật "PostgreSQL ví dụ không làm điều đó" trong PostgreSQL tuần tự sẽ làm tất cả các câu lệnh chọn không có Khóa nhưng khi xảy ra đồng thời không thể cấp toàn vẹn tuần tự – deFreitas

0

Dường như với tôi SERIALIZABLE rằng không thể làm việc trong giao dịch kinh doanh này, bởi vì bạn cần phải kiểm tra một số điều kiện sau khi chọn một thực thể (ví dụ, nếu một tài khoản có đủ tiền bạc). Các giao dịch đồng thời có thể nhận giá trị sai với mức SERIALIZABLE, vì nó giữ khóa chia sẻ (đọc) cho SELECT.

Nhưng SELECT ...CẬP NHẬT sẽ hoạt động bình thường vì nó sẽ giữ một khóa độc quyền cho đến khi kết thúc giao dịch và sẽ buộc các giao dịch khác phải đợi.

Các vấn đề liên quan