假如兩個執行緒同時修改資料庫同一條記錄,就會導致後一條記錄覆蓋前一條,從而引發一些問題。
例如:乙個售票系統有乙個餘票數,客戶端每呼叫一次出票方法,餘票數就減一。
情景:
總共300張票,假設兩個售票點,恰好在同一時間出票,它們做的操作都是先查詢餘票數,然後減一。
一般的sql語句:12
3456
789declare
@
count
as
int
begin
tran
select
@
count
=
count
from
ttt
waitfor delay
'00:00:05'
--模擬併發,故意延遲5秒
update
ttt
set
count
=@
count
-1
commit
tran
select
*
from
ttt
問題就在於,同一時間獲取的餘票都為300,每個售票點都做了一次更新為299的操作,導致餘票少了1,而實際出了兩張票。
開啟兩個查詢視窗,分別快速執行以上**即可看到效果。
定**釋:
悲觀鎖:相信併發是絕大部分的,並且每乙個執行緒都必須要達到目的的。
樂觀鎖:相信併發是極少數的,假設運氣不好遇到了,就放棄並返回資訊告訴它再次嘗試。因為它是極少數發生的。
悲觀鎖解決方案:12
3456
7declare
@
count
as
int
begin
tran
select
@
count
=
count
from
tb
with
(updlock)
waitfor delay
'00:00:05'
--模擬併發,故意延遲5秒
update
tb
set
count
=@
count
-1
commit
tran
在查詢的時候加了乙個更新鎖,保證自查詢起直到事務結束不會被其他事務讀取修改,避免產生髒資料。
從而可以解決上述問題。
樂觀鎖解決方案:12
3456
78910
1112
1314
1516
1718
1920
21--首先給表加一列timestamp
alter
table
ttt
add
timesflag
timestamp
not
null
然後更新時判斷這個值是否被修改
declare
@
count
as
int
declare
@flag
as
timestamp
declare
@rowcount
as
int
begin
tran
select
@
count
=
count
,@flag=timesflag
from
ttt
waitfor delay
'00:00:05'
update
ttt
set
count
=@
count
-1
where
timesflag=@flag
--這裡加了條件
set
@rowcount=@@rowcount
--獲取被修改的行數
commit
tran
--對行數進行判斷即可
if @rowcount=1
print
'更新成功'
else
print
'更新失敗'
這便是樂觀鎖的解決方案,可以解決併發帶來的資料錯誤問題,但不保證每一次呼叫更新都成功,可能會返回'更新失敗'
悲觀鎖和樂觀鎖
悲觀鎖一定成功,但在併發量特別大的時候會造成很長堵塞甚至超時,僅適合小併發的情況。
樂觀鎖不一定每次都修改成功,但能充分利用系統的併發處理機制,在大併發量的時候效率要高很多。
補充:
樂觀鎖通過自定義行版本號字段方式
更新操作時候,防止同一條資料,同時被多人修改,為每條資料新增乙個version欄位
//防止同一條資料,同時被多人修改,為每條資料新增乙個version欄位
1、更新資料之前現獲取該條資料的版本號 version欄位,version欄位設定成預設值0 型別long
select version from your_table where id = #;
2、更新的時候,要將之前查詢出來的version具體值作為條件,同時更新version欄位+1
update your_table set user_name = #, version = version+1 where id = # and version = #;
sqlserver併發處理,鎖和事務
本文系 謝謝 另外這個也不錯 鎖的概述 一.為什麼要引入鎖 多個使用者同時對資料庫的併發操作時會帶來以下資料不一致的問題 丟失更新 a,b兩個使用者讀同一資料並進行修改,其中乙個使用者的修改結果破壞了另乙個修改的結果,比如訂票系統 髒讀 a使用者修改了資料,隨後b使用者又讀出該資料,但a使用者因為某...
SQL Server 備份的併發性
當資料庫正在使用時,sql server 使用乙個聯機備份過程來對資料庫進行備份。在備份過程中,可以進行多個操作 例如 在執行備份操作期間允許使用 insert update 或 delete 語句。在資料庫或事務日誌備份的過程中無法執行的操作包括 如果備份操作與檔案管理操作或收縮操作重疊,則產生衝...
SQLite的併發處理
使用sqlite經常會遇到併發處理,要處理好多執行緒或多程序之間的併發,就得搞清楚sqlite的機制,尤其是sqlite的鎖機制。因為sqlite是檔案資料庫,所以它的鎖也基本是和檔案一致,也即 寫獨佔,讀共享。這意味是在讀取資料庫的時候,是可以多個執行緒共享的,而如果有增刪改的操作,則會獨佔此檔案...