Phân biệt giữa Pessimistic và Optimistic Locking

Locking là một cơ chế RDBMS ngăn chặn người dùng từ nhiều transactions khác nhau gây ra data conflicts. Locking một row giúp ngăn chặn các transactions khác thay đổi row đó cho đến khi transaction đang truy cập vào nó kết thúc. Trong đó có 2 chiến lược lock là: optimistic và pesimistic. Trong bài post này, tôi sẽ giải thích sự khác nhau giữa pessimistic và optimistic locking đối với context của ADF framework.

Pessimistic Locking

Hầu hết các Oracle Developers đều rất quen thuốc với pessimistic locking - một default locking trong BC4J. Cơ chế này hoạt động bằng cách lock một row trước khi một attribute của nó được thay đổi thông qua việc gọi đến method setAttribute(). Nếu có bất kì transaction khác cố gắng truy cập vào row đã bị khóa đó, chúng sẽ bị buộc phải chờ cho đến khi transaction đầu tiên hoàn thành. Cơ chế này sử dụng syntax SELECT...FOR UPDATE. Pessimistic locking là cơ chế locking an toàn nhất bởi việc hai transactions sẽ không bao giờ có thể cùng thay đổi một row. Tuy nhiên, chiến lược locking này có một vài nhược điểm như sau:

  1. Nếu một user chọn edit một record, sau đó, anh ra đi ăn trưa mà chưa kết thúc hay hủy bỏ transaction này. Khi đó, tất cả các users khác cần update record này sẽ buộc phải đợi cho đến khi anh ta trở lại và hoàn thành transaction, hoặc cho đến khi DBA kill transaction này và mở locking.
  2. Có thể xảy ra Deadlock. Khi User A và B cùng update vào Database trong cùng một thời gian. User A sẽ khóa lại record đó và cố gắng mở khóa được hình thành bởi User B cũng đang đợi mở khóa mà User A vừa hình thành.

Pessimistic locking không nên sử dụng cho web applications bởi nó sẽ tạo trạng thái transaction đang chờ xử lý trong cơ sở dữ liệu ở dạng row-level locks. Nếu Pessimistic locking được thiết lập, quản lý trạng thái sẽ làm việc, nhưng chế độ locking sẽ không thực hiện như mong đợi.Mỗi khi một module được recycled, một rollback được cấp phát trong kết nối JDBC. Điều này giải phóng tất cả các khóa mà Pessimistic locking đã tạo ra.

Ví dụ về Pessimistic locking dựa trên lược đồ hr nổi tiếng, giả sử User 1 và User 2 là hai người dùng khác nhau (hai giao dịch riêng biệt) sử dụng Pessimistic locking, cả hai đều cố gắng thay đổi cùng một dãy dữ liệu như sau:

  1. User 1 call EmployeesImpl.setSalary (1000) trên một row cụ thể, do đó, user1 ngay lập tức có được một khóa trên row đó.
  2. Bây giờ người User 2 call EmployeesImpl.setSalary (2000) trên một row tương tự, User 2 cố gắng để có được một khóa trên row và nhận được oracle.jbo.AlreadyLockedException.

Optimistic Locking

Optimistic Locking cho phép nhiều giao dịch có thể hoàn thành mà không ảnh hưởng đến nhau. Oracle đã khuyến cáo việc sử dụng Optimistic Locking cho các ứng dụng web. Thay vì khóa một row ngay khi nó được thay đổi, vớiOptimistic Locking, BC4J chờ đợi cho đến khi row thay đổi được posted trước khi cố gắng để có được một khóa. Một exception sẽ không được throw cho đến khi các giao dịch conflict cố gắng post các thay đổi của chúng vào cơ sở dữ liệu.

Ví dụ về Optimistic Locking, giả sử user1 và user2 là hai người dùng khác nhau (hai giao dịch riêng biệt) bằng cách sử dụng Optimistic Locking, cả hai đều cố gắng thay đổi cùng một dãy dữ liệu như sau:

  1. User1 call EmployeesImpl.setSalary (1000) trên một row cụ thể, user1 không ngay lập tức có được một khóa trên hàng đó.
  2. User2 call EmployeesImpl.setSalary (2000) trên một row tương tự. User1 và User2 hiện có bộ nhớ cache entity khác nhau cho cùng một row.
  3. User 2 call commit() action, như một phần của cycle commit, row đã thay đổi được post lên cơ sở dữ liệu. Trước khi hành động update có thể được thực hiện, User 2 đã có được khóa trên row đó. Khóa sẽ hết hạn ngay lập tức, khi lệnh commit được gửi tới cơ sở dữ liệu.
  4. User 1 bây giờ call commit() action, BC4J cố gắng gửi row đã được thay đổi tới cơ sở dữ liệu, ngay trước khi post nó, nó cố gắng để có được khóa trên row đó. BC4J nhận ra rằng row đã được thay đổi bởi người dùng khác và hành động update row sẽ overwrite lên các thay đổi khác của transaction, do đó, nó sẽ throw một oracle.jbo.RowInconsistentException.

Cuối cùng, bạn có thể sử dụng bất kể loại locking nào. Bạn có thể khóa row bất cứ lúc nào bằng cách call EntityImpl.lock () trên đối tượng entity tương ứng, ngay cả khi chế độ locking là optimistic.

Trên đây là sự khác nhau giữa Persimistic locking và optimistic locking. Tùy theo yêu cầu ứng dụng của mình mà các bạn có thể lựa chọn loại locking phù hợp nhất. Hi vọng bài viết này sẽ có ích cho bạn đọc.

Tài liệu tham khảo

https://mjabr.wordpress.com/2011/06/10/differences-between-pessimistic-and-optimistic-locking/ https://nguyenminhdung.wordpress.com/2009/07/14/khoa-locking/