要實現鐵路售票那樣的效果,若是有票查詢到就鎖定票,若是客人不購買再將票放回票池,這樣能夠保證前來買票的旅客只要查詢到有票就必定可以買到票。咱們能夠經過給數據庫增長一個鎖定的標誌字段來完成,但這裏咱們能夠試試數據庫自己的功能可否實現這個需求。數據庫
首先想到的是事務,若是對一個表開始更新之後,那麼另一個會話查詢這個標的時候,會等待前一個更新數據的會話釋放事務,這是由於普通的SQL讀操做內部其實使用了「已提交讀」的事務隔離級別,能夠保證數據的準確性。可是這不符合咱們的需求,咱們但願另一個查詢會話可以很快的進行查詢,同時過濾掉被「鎖票」的數據。post
在更新會話中,執行下面的查詢:測試
begin tran update Users set Name='aaa' where UID= 610062
新開一個查詢窗口,此時會新開一個鏈接會話,執行一個查詢:spa
select * from LocalDB.dbo.Users
此時發現查詢會話會一直等待,直到更新會話提交事務或者回滾事務:版本控制
begin tran update Users set Name='aaa' where UID= 610062 rollback
再次執行上面的更新會話,但不提交事務,此時,咱們的查詢會話可使用 nolock,不會讓查詢等待。code
select * from LocalDB.dbo.Users(nolock)
可是這樣把前面更新的數據也查詢出來了,不過是舊數據,不符合咱們的需求。此時可使用 行鎖加過濾鎖:blog
select * from LocalDB.dbo.Users with (rowlock,xlock,readpast)
成功實現需求!事務
另外,網友 聽風吹雨 也提供了另外的思路,詳細看下面的查詢代碼:it
use master go ---建立測試數據庫(快照) create database SNAPSHOT_Test go ---激活數據行版本控制 alter database SNAPSHOT_Test set Allow_SNAPSHOT_isolation on go use SNAPSHOT_Test go --1.建立測試表 create table tbReadLevel (ID INT, name nvarchar(20) ) --2新增記錄 insert tbReadLevel select 1,'測試' union select 2,'快照測試' go select ID,name as "修改前數據" from tbReadLevel go --3開啓事務 begin tran update tbReadLevel set name='Jack_upd_快照' where ID=1 --5打開另外一條鏈接 set Transaction isolation level SNAPSHOT select * from tbReadLevel