<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                來自https://zh.wikipedia.org/wiki/%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2 **事務隔離**(英語:Transaction Isolation)定義了[數據庫](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93 "數據庫")系統中一個操作的結果在何時以何種方式對其他[并發](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91 "并發")操作可見。隔離是事務[ACID](https://zh.wikipedia.org/wiki/ACID "ACID")(原子性、一致性性、隔離性、持久性)四大屬性之一。 ## 目錄 [并發控制](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "并發控制")描述了數據庫事務隔離以保證數據正確性的機制。為了保證并行事務執行的準確執行,數據庫和存儲引擎在設計的時候著重強調了并發控制這一點。典型的事務相關機制限制數據的訪問順序([執行調度](https://zh.wikipedia.org/w/index.php?title=%E6%89%A7%E8%A1%8C%E8%B0%83%E5%BA%A6&action=edit&redlink=1))以滿足[可序列化](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E5%BA%8F%E5%88%97%E5%8C%96&action=edit&redlink=1)?和[可恢復性](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7&action=edit&redlink=1)。限制數據訪問意味著降低了執行的性能,并發控制機制就是要保證在滿足這些限制的前提下提供盡可能高的性能。經常在不損害正確性的情況下,為了達到更好的性能,[可序列化](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E5%BA%8F%E5%88%97%E5%8C%96&action=edit&redlink=1)的要求會減低一些,但是為了避免數據一致性的破壞,[可恢復性](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7&action=edit&redlink=1)必須保證。 [兩階段鎖](https://zh.wikipedia.org/w/index.php?title=%E4%B8%A4%E9%98%B6%E6%AE%B5%E9%94%81&action=edit&redlink=1)是關系數據庫中最常見的提供了[可序列化](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E5%BA%8F%E5%88%97%E5%8C%96&action=edit&redlink=1)和[可恢復性](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7&action=edit&redlink=1)的并發控制機制,為了訪問一個數據庫對象,事務首先要獲得這個對象的[鎖](https://zh.wikipedia.org/wiki/%E5%B0%81%E9%94%81_(%E6%95%B0%E6%8D%AE%E5%BA%93) "封鎖 (數據庫)")。對于不同的訪問類型(如對對象的讀寫操作)和鎖的類型,如果另外一個事務正持有這個對象的鎖,獲得鎖的過程會被阻塞或者延遲。 ## 隔離級別[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=2 "編輯小節:隔離級別")] 在[數據庫](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93 "數據庫")事務的[ACID](https://zh.wikipedia.org/wiki/ACID "ACID")四個屬性中,隔離性是一個最常放松的一個。為了獲取更高的隔離等級,數據庫系統的[鎖](https://zh.wikipedia.org/wiki/%E5%B0%81%E9%94%81_(%E6%95%B0%E6%8D%AE%E5%BA%93) "封鎖 (數據庫)")機制或者[多版本并發控制](https://zh.wikipedia.org/w/index.php?title=%E5%A4%9A%E7%89%88%E6%9C%AC%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6&action=edit&redlink=1)機制都會影響[并發](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%80%A7 "并發性")。?[應用軟件](https://zh.wikipedia.org/wiki/%E5%BA%94%E7%94%A8%E8%BD%AF%E4%BB%B6 "應用軟件")也需要額外的邏輯來使其正常工作。 很多[數據庫管理系統](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93 "數據庫")定義了不同的“事務隔離等級”來控制鎖的程度。在很多數據庫系統中,多數的數據庫事務都避免高等級的隔離等級(如可序列化)從而減少對系統的鎖定開銷。程序員需要小心的分析數據庫訪問部分的代碼來保證隔離級別的降低不會造成難以發現的代碼bug。相反的,更高的隔離級別會增加[死鎖](https://zh.wikipedia.org/w/index.php?title=Deadlock&action=edit&redlink=1 "Deadlock(頁面不存在)")發生的幾率,同樣需要編程過程中去避免。 [ANSI](https://zh.wikipedia.org/wiki/ANSI "ANSI")/[ISO](https://zh.wikipedia.org/wiki/ISO "ISO")?[SQL](https://zh.wikipedia.org/wiki/SQL "SQL")定義的標準隔離級別如下: ### 可序列化[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=3 "編輯小節:可序列化")] 最高的隔離級別。 在基于鎖機制[并發控制](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "并發控制")的DBMS實現[可序列化](https://zh.wikipedia.org/w/index.php?title=%E5%8F%AF%E5%BA%8F%E5%88%97%E5%8C%96&action=edit&redlink=1),要求在選定對象上的讀鎖和寫鎖保持直到事務結束后才能釋放。在[SELECT](https://zh.wikipedia.org/wiki/Select_(SQL) "Select (SQL)")?的查詢中使用一個“WHERE”子句來描述一個范圍時應該獲得一個“范圍鎖”(range-locks)。這種機制可以避免“幻影讀”(phantom reads)現象(詳見下文)。 當采用不基于鎖的[并發控制](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "并發控制")時不用獲取鎖。但當系統探測到幾個并發事務有“寫沖突”的時候,只有其中一個是允許提交的。這種機制的詳細描述見“[快照隔離](https://zh.wikipedia.org/w/index.php?title=%E5%BF%AB%E7%85%A7%E9%9A%94%E7%A6%BB&action=edit&redlink=1)” ### 可重復讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=4 "編輯小節:可重復讀")] 在可重復讀(REPEATABLE READS)隔離級別中,基于鎖機制[并發控制](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "并發控制")的DBMS需要對選定對象的讀鎖(read locks)和寫鎖(write locks)一直保持到事務結束,但不要求“范圍鎖”,因此可能會發生“幻影讀”。 ### 提交讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=5 "編輯小節:提交讀")] 在提交讀(READ COMMITTED)級別中,基于鎖機制[并發控制](https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "并發控制")的DBMS需要對選定對象的寫鎖一直保持到事務結束,但是讀鎖在[SELECT](https://zh.wikipedia.org/wiki/Select_(SQL) "Select (SQL)")操作完成后馬上釋放(因此“不可重復讀”現象可能會發生,見下面描述)。和前一種隔離級別一樣,也不要求“范圍鎖”。 ### 未提交讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=6 "編輯小節:未提交讀")] 未提交讀(READ UNCOMMITTED)是最低的隔離級別。允許“臟讀”(dirty reads),事務可以看到其他事務“尚未提交”的修改。 通過比低一級的隔離級別要求更多的限制,高一級的級別提供更強的隔離性。標準允許事務運行在更強的事務隔離級別上。(如在可重復讀隔離級別上執行提交讀的事務是沒有問題的) ## 默認隔離級別[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=7 "編輯小節:默認隔離級別")] 不同的DBMS默認隔離級別也不同。大多數據庫允許用戶設置隔離級別。有些DBMS在執行一個SELECT語句時使用額外的語法來獲取鎖(如*SELECT ... FOR UPDATE*來獲得在訪問的數據行上的排他鎖)。 ## 讀現象舉例[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=8 "編輯小節:讀現象舉例")] ANSI/ISO SQL 92標準涉及三種不同的一個事務讀取另外一個事務可能修改的數據的“讀現象”。 下面的例子中,兩個事務,事務1執行語句1。接著,事務2執行語句2并且提交,最后事務1再執行語句1\. 查詢使用如下的數據表。 users | id | name | age | | 1 | Joe | 20 | | 2 | Jill | 25 | ### 臟讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=9 "編輯小節:臟讀")] 當一個事務允許讀取另外一個事務修改但未提交的數據時,就可能發生臟讀。 臟讀和不可重復讀(non-repeatable reads)類似。事務2沒有提交造成事務1的語句1兩次執行得到不同的結果集。在未提交讀隔離級別唯一禁止的是更新混亂,即早期的更新可能出現在后來更新之前的結果集中。 在我們的例子中,事務2修改了一行,但是沒有提交,事務1讀了這個沒有提交的數據。現在如果事務2回滾了剛才的修改或者做了另外的修改的話,事務1中查到的數據就是不正確的了。 | 事務 1 | 事務 2 | | /* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 20 */ | | | | /* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; /* No commit here */ | | /* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 21 */ | | | | ROLLBACK; /* lock-based DIRTY READ */ | 在這個例子中,事務2回滾后就沒有id是1,age是21的數據行了。 ### 不可重復讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=10 "編輯小節:不可重復讀")] 在一次事務中,當一行數據獲取兩遍得到不同的結果表示發生了“不可重復讀”. 在基于鎖的并發控制中“不可重復讀”現象發生在當執行[SELECT](https://zh.wikipedia.org/wiki/Select_(SQL) "Select (SQL)")?操作時沒有獲得讀鎖或者[SELECT](https://zh.wikipedia.org/wiki/Select_(SQL) "Select (SQL)")操作執行完后馬上釋放了讀鎖;?[多版本并發控制](https://zh.wikipedia.org/w/index.php?title=Multiversion_concurrency_control&action=edit&redlink=1 "Multiversion concurrency control(頁面不存在)")中當沒有要求一個[提交沖突](https://zh.wikipedia.org/w/index.php?title=Commit_conflict&action=edit&redlink=1 "Commit conflict(頁面不存在)")的事務回滾也會發生“不可重復讀”現象。 | 事務 1 | 事務 2 | | /* Query 1 */ SELECT * FROM users WHERE id = 1; | | | | /* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; COMMIT; /* in multiversion concurrency control, or lock-based READ COMMITTED */ | | /* Query 1 */ SELECT * FROM users WHERE id = 1; COMMIT; /* lock-based REPEATABLE READ */ | 在這個例子中,事務2提交成功,因此他對id為1的行的修改就對其他事務可見了。但是事務1在此前已經從這行讀到了另外一個“age”的值。在可序列化(SERIALIZABLE)和可重復讀的隔離級別,數據庫在第二次SELECT請求的時候應該返回事務2更新之前的值。在提交讀和未提交讀,返回的是更新之后的值,這個現象就是不可重復讀。 有兩種策略可以避免不可重復讀。一個是要求事務2延遲到事務1提交或者回滾之后再執行。這種方式實現了**T1, T2**?的串行化[調度](https://zh.wikipedia.org/wiki/%E8%B0%83%E5%BA%A6 "調度")。串行化調度可以支持可重復讀。 另一種策略是*[多版本并發控制](https://zh.wikipedia.org/w/index.php?title=%E5%A4%9A%E7%89%88%E6%9C%AC%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6&action=edit&redlink=1)*。為了得到更好的并發性能,允許事務2先提交。但因為事務1在事務2之前開始,事務1必須在其開始執行時間點的數據庫的快照上面操作。當事務1最終提交時候,數據庫會檢查其結果是否等價于**T1, T2**串行調度。如果等價,則允許事務1提交,如果不等價,事務1需要回滾并拋出個串行化失敗的錯誤。 使用基于鎖的并發控制,在可重復讀的隔離級別中,ID=1的行會被鎖住,在事務1提交或回滾前一直阻塞語句2的執行。在提交讀的級別,語句1第二次執行,age已經被修改了。 在*[多版本并發控制](https://zh.wikipedia.org/w/index.php?title=%E5%A4%9A%E7%89%88%E6%9C%AC%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6&action=edit&redlink=1)*機制下,可序列化(SERIALIZABLE)級別,兩次SELECT語句讀到的數據都是事務1開始的快照,因此返回同樣的數據。但是,如果事務1試圖UPDATE這行數據,事務1會被要求回滾并拋出一個串行化失敗的錯誤。 在提交讀隔離級別,每個語句讀到的是語句執行前的快照,因此讀到更新前后不同的值。在這種級別不會有串行化的錯誤(因為這種級別不要求串行化),事務1也不要求重試。 ### 幻影讀[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=11 "編輯小節:幻影讀")] 在事務執行過程中,當兩個完全相同的查詢語句執行得到不同的結果集。這種現象稱為“幻影讀(phantom read)” 當事務沒有獲取*[范圍鎖](https://zh.wikipedia.org/w/index.php?title=%E8%8C%83%E5%9B%B4%E9%94%81&action=edit&redlink=1)*的情況下執行*[SELECT](https://zh.wikipedia.org/wiki/Select_(SQL) "Select (SQL)")?... WHERE*操作可能會發生“幻影讀”。 “幻影讀”是*不可重復讀*的一種特殊場景:當事務1兩次執行*SELECT ... WHERE*檢索一定范圍內數據的操作中間,事務2在這個表中創建了(如[INSERT](https://zh.wikipedia.org/w/index.php?title=INSERT&action=edit&redlink=1 "INSERT(頁面不存在)"))了一行新數據,這條新數據正好滿足事務1的“WHERE”子句。 | 事務 1 | 事務 2 | | /* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; | | | | /* Query 2 */ INSERT INTO users VALUES ( 3, 'Bob', 27 ); COMMIT; | | /* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; | | 需要指出的是事務1執行了兩遍同樣的查詢語句。如果設了最高的隔離級別,兩次會得到同樣的結果集,這也正是數據庫在可序列化(SERIALIZABLE)隔離級別上需要滿足的。但是在較低的隔離級別上,第二次查詢可能會得到不同的結果集。 在可序列化隔離級別,查詢語句1在age從10到30的記錄上加鎖,事務2只能阻塞直至事務1提交。在可重復讀級別,這個范圍不會被鎖定,允許記錄插入,因此第二次執行語句1的結果中會包括新插入的行。 ## 隔離級別、讀現象和鎖[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=12 "編輯小節:隔離級別、讀現象和鎖")] ### 隔離級別vs讀現象[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=13 "編輯小節:隔離級別vs讀現象")] | 隔離級別 | 臟讀 | 不可重復讀 | 幻影讀 | | --- | --- | --- | --- | | 未提交讀 | 可能發生 | 可能發生 | 可能發生 | | 提交讀 | - | 可能發生 | 可能發生 | | 可重復讀 | - | - | 可能發生 | | 可序列化 | - | - | - | 可序列化(Serializable)隔離級別不等同于可串行化(Serializable)。可串行化調度是避免以上三種現象的必要條件,但不是充分條件。 “可能發生”表示這個隔離級別會發生對應的現象,“-”表示不會發生。 ### 隔離級別vs 鎖持續時間[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=14 "編輯小節:隔離級別vs 鎖持續時間")] 在基于鎖的并發控制中,隔離級別決定了鎖的持有時間。**"C"**-表示鎖會持續到事務提交。?**"S"**?–表示鎖持續到當前語句執行完畢。如果鎖在語句執行完畢就釋放則另外一個事務就可以在這個事務提交前修改鎖定的數據,從而造成混亂。 | 隔離級別l | 寫操作 | 讀操作 | 范圍操作 (...where...) | | --- | --- | --- | --- | | 未提交讀 | S | S | S | | 提交讀 | C | S | S | | 可重復讀 | C | C | S | | 可序列化 | C | C | C | ## 參考文獻[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=15 "編輯小節:參考文獻")] ## 相關條目[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=16 "編輯小節:相關條目")] * [原子性](https://zh.wikipedia.org/w/index.php?title=%E5%8E%9F%E5%AD%90%E6%80%A7&action=edit&redlink=1) * [一致性](https://zh.wikipedia.org/wiki/%E4%B8%80%E8%87%B4%E6%80%A7 "一致性") * [持久性](https://zh.wikipedia.org/w/index.php?title=%E6%8C%81%E4%B9%85%E6%80%A7&action=edit&redlink=1) * [鎖](https://zh.wikipedia.org/wiki/%E5%B0%81%E9%94%81_(%E6%95%B0%E6%8D%AE%E5%BA%93) "封鎖 (數據庫)") * [樂觀并發控制](https://zh.wikipedia.org/wiki/%E4%B9%90%E8%A7%82%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6 "樂觀并發控制") * [關系數據庫](https://zh.wikipedia.org/wiki/%E5%85%B3%E7%B3%BB%E6%95%B0%E6%8D%AE%E5%BA%93 "關系數據庫") * [快照隔離](https://zh.wikipedia.org/w/index.php?title=%E5%BF%AB%E7%85%A7%E9%9A%94%E7%A6%BB&action=edit&redlink=1) ## 外部鏈接[[編輯](https://zh.wikipedia.org/w/index.php?title=%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2&action=edit&section=17 "編輯小節:外部鏈接")] * [Oracle? Database Concepts](http://docs.oracle.com/cd/B12037_01/server.101/b10743/toc.htm),?[chapter 13 Data Concurrency and Consistency, Preventable Phenomena and Transaction Isolation Levels](http://docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm#sthref1919) * [Oracle? Database SQL Reference](http://docs.oracle.com/cd/B19306_01/server.102/b14200/toc.htm),?[chapter 19 SQL Statements: SAVEPOINT to UPDATE](http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10.htm#i2068385),?[SET TRANSACTION](http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10005.htm#i2067247) * in?[JDBC](https://zh.wikipedia.org/wiki/Java_Database_Connectivity "Java Database Connectivity"):?[Connection constant fields](http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#field_summary),?[Connection.getTransactionIsolation()](http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#getTransactionIsolation()),?[Connection.setTransactionIsolation(int)](http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#setTransactionIsolation(int)) * in?[Spring Framework](https://zh.wikipedia.org/wiki/Spring_Framework "Spring Framework"):?[@Transactional](http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html),?[Isolation](http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Isolation.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看