程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 在OLTP的環境下使用大事務出現的問題

在OLTP的環境下使用大事務出現的問題

編輯:關於SqlServer

在應用環境中,常常需要保證幾張表相關數據的一致性,為了應對這種需求,開發工程師常常會使用事務,把一些insert,update等語句綁在一起,形成一個事務(Transaction),比如如下的偽代碼示例(事務1):

begin transaction
insert into messgae(id,col1,col2...) values(#id,#col1,#col2...);
update thread set post_count=nvl(post_count,0) + 1 where id=#v_id;
update test_user set sum_reply = sum_reply + 1 where userid=#v_userid;
end transaction

開發工程師為了實現應用數據完整性的需要,把這幾條SQL綁在一起形成一個大事務,並沒有什麼問題。在OLTP業務發展的早期階段,這樣設計並不會遇到任何問題,並可以最大程度的保證應用層數據的完整性。但隨著OLTP業務量的發展,並發訪問量的快速增長,這個大事務開始出現問題,阻塞現象異常嚴重,導致應用服務器頁面響應時間明顯加長,並已影響到業務的正常運行!經過調查發現,在系統中還存在這樣一個更新SQL(事務2):

update thread set view_count=nvl(view_count,0) + 1 where id=#v_id;

而這個因外界訪問量的增大,執行次數異常的高。很明顯,當事務1執行時,有多個語句要執行,執行時間較長,如果此時有大量的事務2相要執行,我所指的是更新相同的id的記錄。那麼即會發生出現大量的enqueue等待。這是采用當前事務策略下,在OLTP環境下,我們不得不面對的問題.

在剛開始出現大量鎖enqueue等待時,針對事務1,事務2執行頻率的不同:事務1低,事務2高。可以采用一定的策略來減少事務2的數據庫執行次數,比如先將此更新放到緩存裡,每隔一定的時間間隔更新到數據庫裡,減少事務1與事務2的碰撞機會。

隨著OLTP的進一步發展,並發訪問量的進一步提高,因事務1本身的事務較大,事務1發生的頻率也會越來越高,那時,事務1會與事務1本身產生阻塞,那時我們怎麼解決?看來解除事務是唯一的方法,這裡有另外一種觀點,完全解除事務,即把事務1中的每一個語句都拆開,示例如下:

begin transaction
insert into messgae(id,col1,col2...) values(#id,#col1,#col2...);
end transaction

begin transaction
update thread set post_count=nvl(post_count,0) + 1 where id=#v_id;
end transaction

begin transaction
update test_user set sum_reply = sum_reply + 1 where userid=#v_userid;
end transaction

這種方案可以看成事務1的極端,事務1的完全對立面,數據的一致性完全沒有保障。如果數據庫出現down機,或者應用服務器down掉,那麼數據很有可能出現不一致的。為了減少發生數據不一致的概率,可以采用折衷的方案在一定程度上解除事務,事務是一個好東西,就看你怎麼用了!對以上事務1的業務進行分析,發現了如下的規律:

insert into messgae(id,col1,col2...) values(#id,#col1,#col2...);這條SQL可以看成"私有"的,不會產生阻塞(這個表上不能有位圖索引)

update thread set post_count=nvl(post_count,0) + 1 where id=#v_id;這條SQL是"公共"的,很容易發生多個session更新同一條記錄,容易產生阻塞

update test_user set sum_reply = sum_reply + 1 where userid=#v_userid;這條SQL更新自己的東西,也可以看成"私有"的,不會產生阻塞

對以上作分析後,產生了另外一種方案:把"公共"的綁成一個事務,把"私有"的綁成一個事務,原來的事務1變成2個事務,示例如下:

begin transaction1_1
update thread set post_count=nvl(post_count,0) + 1 where id=#v_id;
end transaction1_1

begin transaction1_2
insert into messgae(id,col1,col2...) values(#id,#col1,#col2...);
update test_user set sum_reply = sum_reply + 1 where userid=#v_userid;
end transaction1_2

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved