在數據庫上實現相似鐵路售票鎖票功能

 

要實現鐵路售票那樣的效果,若是有票查詢到就鎖定票,若是客人不購買再將票放回票池,這樣能夠保證前來買票的旅客只要查詢到有票就必定可以買到票。咱們能夠經過給數據庫增長一個鎖定的標誌字段來完成,但這裏咱們能夠試試數據庫自己的功能可否實現這個需求。數據庫

首先想到的是事務,若是對一個表開始更新之後,那麼另一個會話查詢這個標的時候,會等待前一個更新數據的會話釋放事務,這是由於普通的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
複製代碼
相關文章
相關標籤/搜索