悲觀處理方式是 采用SQLSERVER數據庫中“事務+鎖”!
先上偽代碼再解釋:
1.先解釋2個要用到的鎖
SELECT * FROM table WITH (HOLDLOCK) 其他事務可以讀取表,但不能更新刪除
SELECT * FROM table WITH (TABLOCKX) 其他事務不能讀取表,更新和刪除
PS:這2個是表級鎖,要鎖行加上SQL過濾條件即可。數據庫的默認隔離級別是readcommit,
SqlCommand cmd = new SqlCommand("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;select * from Users WITH(rowlock) where id = 2", connection, st);重設事務的隔離級別可以用行鎖。
2.在一個管理頁面執行Update,Delete操作的時候(起碼能得到實體的主鍵ID數據及其修改後的數據),在代碼處理的時候:
客戶A在某個管理頁面執行如下操作
private void button1_Click(object sender, EventArgs e)
{
SqlTransaction st = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
using (st = connection.BeginTransaction())
{
this.Cursor = Cursors.WaitCursor;
SqlCommand cmd = new SqlCommand("select * from Users WITH(HOLDLOCK) where id = 2;update Users set name = 'C羅',address = 'basi' where id = 2", connection, st);
cmd.ExecuteNonQuery();
System.Threading.Thread.Sleep(20000);
st.Commit();
MessageBox.Show("ok。。。s1");
}
}
catch
{
st.Rollback();
}
finally
{
connection.Close();
this.Cursor = Cursors.Default;
}
}
}
客戶B在也在該管理頁面執行如下操作
private void button1_Click(object sender, EventArgs e)
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand cmd = new SqlCommand("update Users set name = '大羅',address = 'basi' where id = 2", connection);
cmd.ExecuteNonQuery();
connection.Close();
MessageBox.Show("ok無事務的提交了");
}
那麼用戶A先進入改管理頁面,並進行修改用戶ID=2的用戶操作,在A用戶操作20秒之內,B用戶也進入該管理頁面進行操作修改用戶ID=2的人,那麼在A用戶修改操作事務提交或回滾或該事務執行失敗之前,用戶B的操作會等待在隊列中,直到A的事務提交釋放悲觀鎖,B的隱式事務才會提交到數據庫。
這樣就保證了數據的一致性。
最後結果是用戶ID=2的名字是大羅(先被改成C羅,後來改成大羅)
業務邏輯的實現過程中,往往需要保證數據訪問的排他性。如在金融系統的日終結算處理中,我們希望針對某個 cut-off 時間點的數據進行處理,而不希望在結算進行過程中(可能是幾秒種,也可能是幾個小時),數據再發生變化。此時,我們就需要通過一些機制來保證這些數據在某個操作過程中不會被外界修改,這樣的機制,在這裡,也就是所謂的 “ 鎖 ” ,即給我們選定的目標數據上鎖,使其無法被其他程序修改。
悲觀鎖( Pessimistic Locking )
悲觀鎖,正如其名,它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個數據處理過程中,將數據處於鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。
一個典型的倚賴數據庫的悲觀鎖調用:
select * from account WITH(HOLDLOCK) where name=”Erica”
這條 sql 語句鎖定了 account 表中所有符合檢索條件( name=”Erica” )的記錄。
本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。
以上就是項目中的采用悲觀處理方式,歡迎大家討論自己的處理方式。