[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.
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 )
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!