18/03/2021, 09:45

[SQLSERVER] Sử dụng RowVersion giải quyết cho giải pháp Optimistic Locking

Xin chào các bạn, bài viết hôm nay mình sẽ nói về cơ chế Locking RDBMS trong database sqlserver nhằm ngăn chặn nhiều transaction từ người dùng khác nhau gây ra data conflicts. Trong đó có 2 chiến lược lock là: Optimistic Locking và Pesimistic Locking ...

Xin chào các bạn, bài viết hôm nay mình sẽ nói về cơ chế Locking RDBMS trong database sqlserver nhằm ngăn chặn nhiều transaction từ người dùng khác nhau gây ra data conflicts.

Trong đó có 2 chiến lược lock là: Optimistic Locking và Pesimistic Locking

Trong bài viết này mình sẽ sử dụng RowVersion trong Sqlserver để giải quyết cho chiến lược Optimistic Locking.

Vậy Optimistic Locking là gì?

Optimistic lock nhiều người dùng có thể cùng truy cập đến đối tượng và đọc dữ liệu từ nó.

Nhưng khi có 2 hay nhiều người dùng muốn update đối tượng đó thì chỉ người truy cập đầu tiên mới có thể update, những người dùng khác sẽ bị bắn ra exception.

1a

Trường hợp locking cụ thể.

Ví dụ: Có 2 người dùng đang load một dòng dữ liệu sản phẩm lên để chỉnh sửa số lượng, giả sử số lượng ban đầu là 10

+ Người dùng thứ 1, update số lượng 10 => 5.

+ Người dùng thứ 2, update số lượng 10 => 6.

Vậy theo như bình thường lưu thì 2 người sẽ update đè cho vào một dòng dữ liệu gây ra hiện tượng conflicts data.

Cơ chế Optimistic locking trong trường hợp này, chỉ cho phép người dùng nào update đầu tiên sẽ update thành công, người dùng sau update sẽ không thành công.

Vì vậy trong mỗi trường dữ liệu, mình sẽ thêm một column RowVersion.

Rowversion là một kiểu timestamp chỉ readonly, khi dữ liệu trong dùng của chúng ta update thay đổi, thì column này cũng thay đổi theo.

Vd: mình tạo bảng table Customer trong sqlserver.

CREATE TABLE Customer (
  Id int IDENTITY (1, 1) NOT NULL,
  FirstName nvarchar (256) NULL,
  LastName nvarchar (256) NULL,
  _rowVersion rowversion NOT NULL -- Value generated by SQL Server each time the row is updated
)

sqlsever_locking

row_version

Bây giờ, mình sẽ chạy update dữ liệu.

UPDATE Customer SET
  FirstName = @FirstName,
  LastName] = @LastName,
WHERE Id = @Id AND _rowVersion] = @_rowVersion -- Update using the row version


SELECT @rowcount = @@ROWCOUNT
IF(@rowcount = 0) -- No row updated => Concurrency Error
BEGIN
    RAISERROR ('Concurrency error in procedure %s', 16, 1, 'Customer_Save')
    RETURN
END

theo từ khóa where là _rowVersion

Vậy theo lệnh trên chúng ta đã giải quyết được vấn đề.

Người dùng đầu tiên update sẽ thành công, và những người dùng sau cập nhật sẽ không thành công.

Thanks for watching!

Tags: optimistic lockingrowversion sql
0