1. 程式人生 > >淺談Sybase封鎖原理和解決方

淺談Sybase封鎖原理和解決方


  一、 調整死鎖檢測間隔
  ① 通過配置引數“print deadlock information”的設定,在ASE的日誌中顯示死鎖發生的情形。
  ② 如果應用很少發生死鎖現象,則可以使用引數deadlock checking period來指定進行死鎖檢查之前程序的等待時間,這樣可以延遲死鎖檢查而降低開銷。
  ③ deadlock checking period 的取值範圍是0-2147483預設值是500,即一程序至少等待500ms後,ASE才準備檢查死鎖。

  二、死鎖預防
  ① 為儘可能避免死鎖的出現在所有的事務中都按同一順序來訪問各個表。
儘可能利用儲存過程來完成一個事務,以能夠保證對各表的訪問次序都是一致的。除非有“可重複讀”的必要性,否則不要使用holdlock選項。
  ② 事務應縮小且應儘快提交。
  ③ 避免人工輸入操作出現在事務中或是同時對該表施加holdlock。
  ④ 避免併發地執行許多像insert,update,delete這類資料修改語句。

  三、資料庫鎖的配置原則

  ① 鎖的數量不要太小,如果鎖不夠,可通過命令 sp_configure “number of locks”,NUM 進行修改。
  ② 如果需要節省空間,減少維護量,使用所有頁鎖機制。
  ③ 如果需要加快速度,空間足夠,使用資料頁鎖機制。
  ④ 當通過監測發現鎖競爭超過15%時,首先修改加鎖最重的表的鎖機制,然後再把資料頁鎖設定為資料行鎖。如果發現螺旋鎖多,則為該表建立單獨的命名快取並對命名快取進行分割槽。
這裡舉兩個有用的例項,可幫助讀者獲取一些系統引數,用於分析是否需要更改引數配置。
例項1:執行sp_sysmon “00:05:00” 系統取樣(報告在5分鐘內關於資料緩衝區統計資訊,可確定是否I/O開銷太大等)
DBCC execution completed。 If DBCC printed error messages, contact a user with
System Administrator (SA) role。
Sybase Adaptive Server Enterprise System Performance Report
===============================================================================
Server Version: Adaptive Server Enterprise/11。9。2。6/1290/P/EBF 10487 ESD
Server Name: Server is Unnamed
Run Date: Dec 27, 2005
Statistics Cleared at: 10:46:59
Statistics Sampled at: 10:51:59
Sample Interval: 00:05:00
(以下預設,如想檢視詳細資訊,請執行sp_sysmon “00:05:00”)
例項2:執行sp_object_stats “00:05:00”,10,db1(此命令是將5分鐘之內競爭激烈的頭10個表列出來)
Lock statistics for the top 10 (or less) most contended objects:
Object Name: db1..table1 (dbid=7, objid=555305188, lockscheme=Datarows):-
Row Locks SH_ROW UP_ROW EX_ROW
---------- ---------- ---------- ----------
Grants: 969 0 50
Waits: 3 0 0
Deadlocks: 0 0 0
Wait-time: 6790 ms 0 ms 0 ms
Contention: 0。31% 0。00% 0。00%
Object Name: db1..table3 (dbid=7, objid=1927834080, lockscheme=Allpages):-
Page Locks SH_PAGE UP_PAGE EX_PAGE
Grants: 273760 5880 324
Waits: 16 0 0
Deadlocks: 0 0 0
Wait-time: 684 ms 0 ms 0 ms
Contention: 0。01% 0。00% 0。00%
(以下預設,如想檢視詳細資訊,請執行sp_object_stats“00:05:00”,10,db1)
從中可看出table3事全頁鎖,table1是資料行鎖,表的競爭都在可接受的範圍內,沒有需要調整的配置。

  四、資料庫鎖的提升機制

  ㈠、提升鎖時幾個命令
  ① ASE中對所有的表都予置了隱含的全頁面加鎖機制,可用命令
sp_configure “lock scheme”,[allpages|datapages|datarows] 檢視鎖的型別。當資料庫從原先版本的伺服器中轉儲出來重新載入時,所有的表都被定義為全頁面加鎖的表。
  ② 當建立一個新表時,可以不使用這個預設值,而採用如下的句法格式:
create table <tablename>…lock[allpages|datapages|datarows]
  ③ 為了在使用的一個表中改變加鎖型別,可以採用如下的句法格式:
alter table <tablename> lock[allpages|datapages|datarows]
  ㈡、提升鎖時需注意幾個問題
  鎖提升是同類型的提升,Share Page Lock à Share Table Lock,鎖提升的前提條件是在該表上不能有其他型別的鎖,比如表A上有共享頁鎖,當共享頁鎖的數目達到引數“ page lock promotion HWM”的值並且表A上沒有其他的鎖時,會提升到表級共享鎖。在一個現存的表中改變加鎖方式,將引起下列三種行動後果發生:
  首先,如果一張表從全頁加鎖轉變為僅對資料加鎖,或者從僅對資料加鎖轉變為全頁加鎖,在這兩種型別之間就要對錶進行選擇以允許進行存貯格式改變。如果這是一個分割槽表,就要同時假定必要的並行級別和工作執行緒已經配置好的情況下,才能執行。其次,對錶中的群聚性索引必須重新建立。因為我們要保證資料,所以如果從全頁加鎖方式轉換為只對資料加鎖時,這種重新建立可以通過“with sorted_data”來完成。然而,當從僅對資料加鎖機制轉換為全頁加鎖方式時,就要進行並行的索引建立操作。(請注意:如果這是一個分割槽表時,那麼並行等級和工作執行緒的數目必須加以配置才能允許進行這種改變,否則這種遷移將會失敗)。最後,非群聚性的索引將被重建。
  由於這些活動同潛在的工作量有關,從全頁加鎖機制改變為僅對資料加鎖或從僅對資料加鎖改變為全頁加鎖機制都可能是耗費時間的活動。為了標註這一點,有以下一些選擇:如果可能的話,應該配置使用並行方式。這至少對執行非群聚性索引的哈斯(雜湊,即hashed)建立方法是必須的,但是如果可能的話,採用分割槽表和分割槽掃描將使系統得到更大的改進。在選擇進入和建立群聚性的索引之後,該任務將被設定檢查點(checkpointed)。所以如果有充分的硬體資源,通過允許在任何一個時間點上,檢查點任務可以具有多於10個(系統預設值)的非同步I/O請求,利用dbcc進行調諧將能夠帶來有益的效果。(“maxwritedes”,number) 進一步作為降低使用檢查點成本的一種方法,在相關的高速緩衝池(cache pool)、大資料量的I/O操作中,採用對高淘汰程度進行標記的方法,並允許清潔程式(好象家庭主婦一樣)保持特別活躍的狀態,將為那些檢查點需要從高速緩衝池中,重新整理較“髒”的頁面的而增加的I/O操作次數,並因此花費了在檢查點上的時間都能夠大大減少作出貢獻。如果預先進行了配置,則可以對並行的選擇進入可以使用預先分配的盤區。所以,通過將sp_configure “number of pre-allocated extent”設定為16也將對系統性能有明顯的積極的效果。

  五、定位出錯處

  根據sp_who與sp_lock2命令的結果,結合sysobjects和相應的操作員的資訊表。得到操作員及其在死鎖時所操作的庫表,便大約可以知道應用程式的出錯處,再執行dbcc traceon(3604)以進一步認證。最後查詢程式並修正之。 有一段時間,筆者維護的資料庫頻繁出現死鎖,檢視資料庫也沒有什麼大的操作,cpu利用率也在合理範圍內,是什麼引起資料庫頻繁死鎖呢,筆者用了以下幾步命令,找到了原因:
  ① select * from master syslogshold 執行後發現有一個程序超過了24小時未釋放(記下程序的spid號),但這個程序執行了什麼命令不能判斷。(syslogshold表記錄最老的仍活動的事務, 要查詢每一資料庫在應用中有最老的活動的事務及其開始時間。)
  ② dbcc traceon(3604) 開啟資料庫的開關,設定輸出到螢幕。
  ③ dbcc sqltext(程序號) 這時我們會看到引起阻塞,不能釋放的sql語句。
通過以上三步,筆者當時看到引起阻塞不能釋放的sql語句只是普通的select語句,但是對同一張表反覆提取資料,在對源程式研究後發現在select語句執行後,沒有提交事務的語句(即commit),而該程式被廣泛使用,造成程序阻塞不斷增加,最終導致互鎖。找到問題根源後,及時對程式調優,死鎖現象在未發生。由此也可看出,在沒有進行大的操作時,當程序定義user_transtion 的程序超過60分鐘,就應該檢查應用程式,調整不合理的程式或業務流程。