一、數據庫事務
1、事務是作為單個邏輯工作單元執行的一系列操作。可以是一條SQL語句也可以是多條SQL語句。
2、事務具有四個特性
原子性:不可分隔、成則具成、敗則具敗。
恢灤裕菏攣裨諭瓿墑保 匭朧顧 械氖 荻急3忠恢倫刺?
隔離性:獨立的執行互不干擾。由并發事務所作的修改必須與任何其他并發事務所作的修改隔離(另外的描述:多個事務同時進行,它們之間應該互不干擾.應該防止一個事務處理其他事務也要修改的數據時,不合理的存取和不完整的讀取數據)
3、啟動事務:使用 API 函數和 Transact-SQL 語句,可以按顯式、自動提交或隱式的方式來啟動事務。
4、結束事務:您可以使用 COMMIT(成功) 或 ROLLBACK(失敗) 語句,或者通過 API 函數來結束事務。
5、創建事務的原則:
盡可能使事務保持簡短很重要,當事務啟動后,數據庫管理系統 (DBMS) 必須在事務結束之前保留很多資源、以保證事務的正確安全執行。
特別是在大量并發的系統中, 保持事務簡短以減少并發 資源鎖定爭奪,將先得更為重要。
1、事務處理,禁止與用戶交互,在事務開始前完成用戶輸入。
2、在瀏覽數據時,盡量不要打開事務
3、盡可能使事務保持簡短。
4、考慮為只讀查詢使用快照隔離,以減少阻塞。
5、靈活地使用更低的事務隔離級別。
6、靈活地使用更低的游標并發選項,例如開放式并發選項。
7、在事務中盡量使訪問的數據量最小。
二、事務的隔離級別
1、數據庫事務的隔離級別:四種
隔離級別 |
臟讀(Dirty Read) |
不可重復讀(NonRepeatable Read) |
幻讀(Phantom Read) |
讀未提交(Read uncommitted) |
可能 |
可能 |
可能 |
讀已提交(Read committed) |
不可能 |
可能 |
可能 |
可重復讀(Repeatable read) |
不可能 |
不可能 |
可能 |
可串行化(Serializable ) |
不可能 |
不可能 |
不可能 |
2、數據庫一般的默認隔離離級別是“讀已提交”,默認的事務隔離級別下:Insert,update ,delete下的是X鎖, 會等待事務完成。通常情況下可以把隔離級別設為Read Commited,它能避免臟讀,而且有較好的并發性能。盡管它會導致不可重復讀、虛讀和第二類更新丟失等問題,在可能出現這類問題的個別場合可以由應用程序釆用悲觀鎖或樂觀鎖來控制。
3、SQL語句可以使用SET TRANSACTION ISOLATION LEVEL來設置事務的隔離級別。如:SET TRANSACTION ISOLATION LEVEL Read Committed。若要在應用程序中使用更嚴格或較寬松的隔離級別,可以通過使用 set transaction isolation level語句設置會話的隔離級別,來自定義整個會話的鎖定。
指定隔離級別后,sql server會話中所有select語句的鎖定行為都運行于該隔離級別上,并一直保持有效直到會話終止或者將隔離級別設置為另一個級別。
4、另外要提一點:SQL標準對事務隔離級別的規定,是按該級別不可能發生什么問題來確定的,不一定會發生這樣的問題;所以,不同的數據庫對事務隔離的級別約定不一樣,比如,有的數據庫把 可重復讀級別按可串行化來對待。(lkdlhw_2000個人理解:各個數據庫應該都遵循四種標準的事務隔離等級的定義,但是某些數據庫具體實現可能不存在四種,因為串行化可以避免不可重復讀,因此某些數據庫語法上支持設置事務隔離等級為不可重復讀,但實際上是串行化在起作用。也就是說只要該級別能夠避免不可重復讀的問題,就可以稱之為不可重復讀取級別。)
5、該隔離級別定義一個事務必須與其他事務所進行的資源或數據更改相隔離的程度。事務隔離級別控制:
讀取數據時是否占用鎖以及所請求的鎖類型。
占用讀取鎖的時間。
引用其他事務修改的行的讀取操作是否:
在該行上的排他鎖被釋放之前阻塞其他事務。
檢索在啟動語句或事務時存在的行的已提交版本。
讀取未提交的數據修改
三、鎖
1、分類:從數據庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖
2、事務使用鎖,防止其他用戶修改另外一個還沒有完成的事務中的數據。對于多用戶系統來說,鎖機制是必須的。SQL Server有多種鎖,允許事務鎖定不同的資源。鎖就是保護指定的資源,不被其他事務操作。SQL Server有多種鎖,允許事務鎖定不同的資源。鎖就是保護指定的資源,不被其他事務操作。為了最小化鎖的成本,SQL Server自動地以與任務相應等級的鎖來鎖定資源對象。鎖定比較小的對象,例如鎖定行,雖然可以提高并發性,但是卻有較高的開支,因為如果鎖定許多行,那么需要占有更多的鎖。鎖定比較大的對象,例如鎖定表,會大大降低并發性,因為鎖定整個表就限制了其他事務訪問該表的其他部分,但是成本開支比較低,因為只需維護比較少的鎖。
3、 鎖的特點:
1. 鎖是保證并發控制的手段
2. 可以鎖定的資源包括行、頁、簇、表和數據庫
3. 鎖的類型主要包括共享鎖和排它鎖
4. 特殊類型的鎖包括意圖鎖、修改鎖和模式鎖
5. 共享鎖允許其他事務繼續使用鎖定的資源
6. 排它鎖只允許一個事務訪問數據
7. 系統本身可以處理死鎖
8. 用戶可以根據實際情況定制鎖的一些特征
4、鎖是定義到sql語句上的,對數據進行操作的sql就是:select,Insert,update ,delete。不同的事物隔離即被在執行sql的時候會向表上發送不同的鎖。
關于鎖的更多描述,可以去網上搜索一下。http://www.bitscn.com/windows/sql/200604/1068.html
四、多個用戶同時對數據庫的并發操作時會帶來以下數據不一致的問題:
臟讀dirty reads:
當事務讀取還未被提交的數據時,就會發生這種事件。舉例來說:Transaction1修改了一行數據,然后Transaction2在Transaction1還未提交修改操作之前讀取了被修改的行。如果Transaction1回滾了修改操作,那么Transaction2讀取的數據就可以看作是從未存在過的。
不可重復的讀non-repeatable reads:
當事務兩次讀取同一行數據,但每次得到的數據都不一樣時,就會發生這種事件。舉例來說:Transaction1讀取一行數據,然后Transaction2修改或刪除該行并提交修改操作。當Transaction1試圖重新讀取該行時,它就會得到不同的數據值(如果該行被更新)或發現該行不再存在(如果該行被刪除)。
虛讀phantom read:
如果符合搜索條件的一行數據在后面的讀取操作中出現,但該行數據卻不屬于最初的數據,就會發生這種事件。舉例來說Transactio1讀取滿足某種搜索條件的一些行,然后Transaction2插入了符合Transaction1的搜索條件的一個新行。如果Transaction1重新執行產生原來那些行的查詢,就會得到不同的行。
為了解決這些問題,數據庫引入了“鎖”的機制(從數據庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖,詳細內容不再描述)。
五、lkdlhw_2000個人理解(以下問題都是推測,還沒有證實):
隔離級別是由鎖來實現的,之所以出現事務的隔離級別相當于數據庫開發商根據一般的業務需求實現定義好的一組鎖使用的規則,便于我們時候,當我們將事務隔離級別定義到某一級上后如果不能滿足需求,我們還可以自行定義sql的鎖來覆蓋事務隔離級別默認的鎖機制?
鎖存在兩個問題:一個是鎖的粒度,一個是鎖的時間,鎖的時間應該包括兩種一種是sql執行完就釋放鎖,領一中是事務結束后釋放鎖
六、參考文章
http://www.es-ivision.com/Channel-4-10-108-0.html
http://tech.ccidnet.com/art/1105/20050602/261573_1.html
http://www.tkk7.com/zhengtengfeng/archive/2007/04/23/113025.html
七、事務隔離級別的例子
1. Read Uncommitted:最低等級的事務隔離,僅僅保證了讀取過程中不會讀取到非法數據。上訴4種不確定情況均有可能發生。
2. Read Committed:大多數主流數據庫的默認事務等級,保證了一個事務不會讀到另一個并行事務已修改但未提交的數據,避免了“臟讀取”。該級別適用于大多數系統。
第一個查詢事務
SET TRANSACTION ISOLATION LEVEL Read Committed
begin tran
update Cate SET Sname=Sname+'b' where ID=1
SELECT * FROM cate where ID=1
waitfor delay '00:00:6'
rollback tran --回滾事務
select Getdate()
SELECT * FROM cate where ID=1
第二個查詢事務
SET TRANSACTION ISOLATION LEVEL Read committed --把committed換成Read uncommitted可看到“臟讀取”的示例。
SELECT * FROM cate where ID=1
select Getdate()
可以看到使用 Read Committed 成功的避免了“臟讀取”.
3. Repeatable Read:保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的數據。避免了“臟讀取”和“不可重復讀取”的情況,但是帶來了更多的性能損失。
第一個查詢事務
SET TRANSACTION ISOLATION LEVEL Repeatable Read -- 把Repeatable Read換成Read committed可以看到“不可重復讀取”的示例
begin tran
SELECT * FROM cate where ID=33 --第一次讀取數據
waitfor delay '00:00:6'
SELECT * FROM cate where ID=33 --第二次讀取數據,不可重復讀取
commit
第二個查詢事務
SET TRANSACTION ISOLATION LEVEL Read committed
update cate set Sname=Sname+'JD' where ID=33
SELECT * FROM cate where ID>30
4. Serializable:最高等級的事務隔離,上面3種不確定情況都將被規避。這個級別將模擬事務的串行執行。
在第一個查詢窗口執行
SET TRANSACTION ISOLATION LEVEL Serializable -- 把Serializable換成Repeatable Read 可看到“幻像讀”的示例
begin tran
SELECT * FROM cate where ID>30 --第一次讀取數據,“幻像讀”的示例
waitfor delay '00:00:6' --延遲6秒讀取
SELECT * FROM cate where ID>30 --第一次讀取數據
commit
第二個查詢事務
SET TRANSACTION ISOLATION LEVEL Read committed
Delete from cate where ID>33
SELECT * FROM cate where ID>30
創建事務
設置事務級別:SET TRANSACTION ISOLATION LEVEL
開始事務:begin tran
提交事務:COMMIT
回滾事務:ROLLBACK
創建事務保存點:SAVE TRANSACTION savepoint_name
回滾到事務點:ROLLBACK TRANSACTION savepoint_name
1、并發的影響:
http://technet.microsoft.com/zh-cn/library/ms190805.aspx
該文章列出了并發引起的四種影響:丟失更新、臟讀(未提交的依賴關系)、不可重復讀(不一致的分析)、幻讀
2、并發控制類型:
http://technet.microsoft.com/zh-cn/library/ms189132.aspx
當許多人試圖同時修改數據庫中的數據時,必須實現一個控制系統,使一個人所做的修改不會對他人所做的修改產生負面影響。這稱為并發控制。并發控制類型分為兩大類:樂觀并發控制和悲觀并發控制
3、數據庫引擎中的隔離級別:
http://technet.microsoft.com/zh-cn/library/ms189122.aspx
1)講到了事務隔離級別控制的內容:
事務隔離級別控制:
讀取數據時是否占用鎖以及所請求的鎖類型。
占用讀取鎖的時間。
引用其他事務修改的行的讀取操作是否:
在該行上的排他鎖被釋放之前阻塞其他事務。
檢索在啟動語句或事務時存在的行的已提交版本。
讀取未提交的數據修改。
2)列出了事務的隔離級別:
未提交讀(隔離事務的最低級別,只能保證不讀取物理上損壞的數據)
已提交讀(數據庫引擎的默認級別)
可重復讀
可序列化(隔離事務的最高級別,事務之間完全隔離)
3)選擇事務隔離級別不影響為保護數據修改而獲取的鎖。事務總是在其修改的任何數據上獲取排他鎖并在事務完成之前持有該鎖,不管為該事務設置了什么樣的隔離級別。對于讀取操作,事務隔離級別主要定義保護級別,以防受到其他事務所做更改的影響。
4、SET TRANSACTION ISOLATION LEVEL (Transact-SQL) 設置事務隔離級別
http://technet.microsoft.com/zh-cn/library/ms173763.aspx
該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 HOLDLOCK 相同
5、總結:
通過以上幾篇文章基本上可以了解數據庫事務和鎖之間的關系。數據庫事務隔級別也是由鎖機制來最實現的。要想了解關于鎖的更深層析的內容還需要專門學習鎖的相關知識。