數據庫事務應用編程規範

一、            編寫有效事務的指導原則

  • 不要在事務處理期間要求用戶輸入或消息響應。

在事務啓動之前,獲得所有需要的用戶輸入。如果在事務處理期間還需要其它的用戶輸入,則回滾當前的事務,並在提供了用戶輸入之後重新啓動該事務。即使用戶立即響應,作爲人,其反應時間也要比計算機慢得多。事務佔用的所有資源都要保持很長的時間,這就有可能造成阻塞問題。如果用戶沒有響應,該事務就會仍保持活動狀態,並鎖定關鍵資源,直到他們響應爲止,但是用戶可能會幾分鐘甚至幾小時都不響應。

  • 在瀏覽數據時,儘量不要打開事務。

在所有預備的數據分析完成之前,不應啓動事務。

保持事務儘可能地短。

  • 在知道了必須要進行的修改之後,啓動事務,執行修改語句,然後立即提交或回滾。只有在需要時,纔打開事務。不要在發出更新語句後,再次進行復雜計算生成數據,再提交和回滾。
  • 靈活地使用更低的事務隔離級別。

可以很容易地編寫出許多使用授權讀事務隔離級別的應用程序。並不是所有的事務都要求可串行事務隔離級別。

  • 靈活地使用更低的遊標併發選項,如樂觀併發選項。

在很少有可能併發更新的系統中,處理某個偶然的"別人在您讀取數據後更改了該數據"錯誤的開銷,要比在讀取數據時始終鎖定行的開銷小得多。

  • 在事務中儘量使訪問的數據量最小。

這樣可以減少鎖定的行數,從而減少事務之間的爭奪。

二、            避免死鎖:

下列方法有助於最大限度地降低死鎖:

·                    按同一順序訪問對象。

·                    避免事務中的用戶交互。

·                    保持事務簡短並在一個批處理中。

·                    使用低隔離級別。

三、            觸發器

 

不要嘗試在觸發器中定義事務,包括begin tran,commit,rollback。

 

四、            存儲過程:

存儲過程對@@TRANCOUNT應無淨改變,如果 @@TRANCOUNT 的值在存儲過程完成時與過程執行時不同,則會生成一個 266 信息類錯誤.

當調用存儲過程時,如果 @@TRANCOUNT 爲 1 或更大,並且該過程執行 ROLLBACK TRANSACTION 或ROLLBACK WORK 語句,則會產生 266 號錯誤。這是因爲 ROLLBACK 回滾所有未完成的事務,並將 @@TRANCOUNT 減到 0,該值比調用過程時要小。

存儲過程既可以被前臺執行,也可以在後臺執行,凡涉及更新數據的存儲過程,在定義事務時應嚴格遵守以下約定:

--以下爲標準存儲過程事務定義的模板
Create procedure proc_test
As
begin
declare @is_procedure_transaction char(1)	--是否是存儲過程定義的事務
declare @local_error	int					--保存更新錯誤號

if @@trancount = 0 	--判斷事務是否嵌套,如無則存儲過程自己定義事務
begin
	select @is_procedure_transaction=’1’	--將存儲過程定義的事務標誌置’1’
	begin tran tran_procedure			--存儲過程自己定義事務
end 

--此處爲INSERT,UPDATE,DELETE等更新操作語句,並假定是存儲過程中最後一個更新語句,如果不是最後的更新語句,僅處理錯誤部分
if @@error <> 0		--判斷數據庫更新時是否有錯誤發生
begin		--更新有錯誤
	set @local_error =  @@error
	if @is_procedure_transaction=’1’ 	--判斷事務是否由存儲過程定義
	begin
		rollback tran	--錯誤發生則回滾存儲過程定義的事務,注意不要帶事務名
	end 
	--close cursorname		如果定義有遊標,請關閉
	--deallocate cursorname	如果定義有遊標,請釋放
	raiserror('數據更新錯誤,SQL錯誤號='+convert(varchar(6), @local_error),16,1)		--返回錯誤信息,並顯示SQL錯誤號
	return -1
end 	--更新有錯誤處理結束
else
begin	--更新成功
	if @is_procedure_transaction=’1’ 		--判斷事務是否由存儲過程定義
	begin
		commit tran	--更新成功則提交存儲過程定義的事務,注意不要帶事務名
	end
	--close cursorname		如果定義有遊標,請關閉
	--deallocate cursorname	如果定義有遊標,請釋放
	return 0
end	--更新成功處理結束
		end 	--結束整個存儲過程
go

五、            隔離級別與鎖模式

 

l 數據一致性要求與併發性要求是一個矛盾體,數據一致性要求高則併發性就差,否則併發性要求高則數據一致性要求相對要求就低一些。應根據具體情況處理。

l 爲避免髒讀、不可重複讀取或幻像讀取,引入數據事務隔離級別定義:SET TRANSACTION ISOLATION LEVEL { READ COMMITTED| READUNCOMMITTED| EPEATABLE READ| SERIALIZABLE }一次只能設置這些選項中的一個,而且設置的選項將一直對那個連接保持有效,直到顯式更改該選項爲止。這是默認行爲,除非在語句的 FROM 子句中在表級上指定優化選項。SET TRANSACTIONISOLATION LEVEL 的設置是在執行或運行時設置,而不是在分析時設置。其中READCOMMITTED爲Mssqlserver的默認設置。

可以使用 SELECT、INSERT、UPDATE和 DELETE 語句指定表級鎖定提示的範圍,以引導 MSSQLServer 使用所需的鎖類型。當需要對對象所獲得鎖類型進行更精細控制時,可以使用表級鎖定提示。這些鎖定提示取代了會話的當前事務隔離級別。 SQL Server 查詢優化器自動作出正確的決定。建議僅在必要時才使用表級鎖定提示更改默認的鎖定行爲。舉例如下:

USE pubs
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
SELECT au_lname FROM authors WITH (NOLOCK)
GO
EXEC sp_lock
GO

檢查加鎖情況發現引用 authors 唯一採用的鎖是架構穩定性 (Sch-S) 鎖。在這種情況下不能保證可串行性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章