<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Decode360's Blog

    業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
      397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
    ORACLE的隔離級別
    ???????????????? 作者: Parrotao
    ?
    隔離級別(isolation level)
    ?
    ??? 隔離級別定義了事務與事務之間的隔離程度。
    ??? 隔離級別與并發性是互為矛盾的:隔離程度越高,數據庫的并發性越差;隔離程度越低,數據庫的并發性越好。
    ??? ANSI/ISO SQL92標準定義了一些數據庫操作的隔離級別:
    ??????? 未提交讀(read uncommitted)
    ??????? 提交讀(read committed)
    ??????? 重復讀(repeatable read)
    ??????? 序列化(serializable)
    ?
    ??? 通過一些現象,可以反映出隔離級別的效果。這些現象有:
    ??? 更新丟失(lost update):當系統允許兩個事務同時更新同一數據是,發生更新丟失。
    ??? 臟讀(dirty read):當一個事務讀取另一個事務尚未提交的修改時,產生臟讀。
    ??? 非重復讀(nonrepeatable read):同一查詢在同一事務中多次進行,由于其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生非重復讀。(A transaction rereads data it has previously read and finds that another committed transaction has modified or deleted the data.)
    ??? 幻像(phantom read):同一查詢在同一事務中多次進行,由于其他提交事務所做的插入操作,每次返回不同的結果集,此時發生幻像讀。(A transaction reexecutes a query returning a set of rows that satisfies a search condition and finds that another committed transaction has inserted additional rows that satisfy the condition.)
    ?
    ??? 下面是隔離級別及其對應的可能出現或不可能出現的現象:
    ?
    isolation level
    Dirty Read ?
    NonRepeatable Read ?
    Phantom Read ?
    Read uncommitted Possible Possible Possible
    Read committed Not possible Possible Possible
    Repeatable read Not possible Not possible Possible
    Serializable Not possible Not possible Not possible
    ?
    ?
    ORACLE的隔離級別
    ?
    ??? ORACLE提供了SQL92標準中的read committed和serializable,同時提供了非SQL92標準的read-only。
    ?
    ??? read committed:
    ??????? 這是ORACLE缺省的事務隔離級別。
    ??????? 事務中的每一條語句都遵從語句級的讀一致性。
    ??????? 保證不會臟讀;但可能出現非重復讀和幻像。
    ?
    ??? serializable:
    ??????? 簡單地說,serializable就是使事務看起來象是一個接著一個地順序地執行。
    ??????? 僅僅能看見在本事務開始前由其它事務提交的更改和在本事務中所做的更改。
    ??????? 保證不會出現非重復讀和幻像。
    ??????? Serializable隔離級別提供了read-only事務所提供的讀一致性(事務級的讀一致性),同時又允許DML操作。
    ?
    ??????? 如果有在serializable事務開始時未提交的事務在serializable事務結束之前修改了serializable事務將要修改的行并進行了提交,則serializable事務不會讀到這些變更,因此發生無法序列化訪問的錯誤。(換一種解釋方法:只要在serializable事務開始到結束之間有其他事務對serializable事務要修改的東西進行了修改并提交了修改,則發生無法序列化訪問的錯誤)
    ?
    ??????? If a serializable transaction contains data manipulation language (DML) that attempts to update any resource that may have been updated in a transaction uncommitted at the start of the serializable transaction, (并且修改在后來被提交而沒有回滾), then the DML statement fails. 返回的錯誤是ORA-08177: Cannot serialize access for this transaction。
    ?
    ??????? ORACLE在數據塊中記錄最近對數據行執行修改操作的N個事務的信息,目的是確定是否有在本事務開始時未提交的事務修改了本事務將要修改的行。具體見英文:Oracle permits a serializable transaction to modify a data row only if it can determine that prior changes to the row were made by transactions that had committed when the serializable transaction began. To make this determination efficiently, Oracle uses control information stored in the data block that indicates which rows in the block contain committed and uncommitted changes. In a sense, the block contains a recent history of transactions that affected each row in the block. The amount of history that is retained is controlled by the INITRANS parameter of CREATE TABLE and ALTER TABLE. Under some circumstances, Oracle may have insufficient history information to determine whether a row has been updated by a "too recent" transaction. This can occur when many transactions concurrently modify the same data block, or do so in a very short period. You can avoid this situation by setting higher values of INITRANS for tables that will experience many transactions updating the same blocks. Doing so will enable Oracle to allocate sufficient storage in each block to record the history of recent transactions that accessed the block.
    ?
    ??????? The INITRANS Parameter:Oracle stores control information in each data block to manage access by concurrent transactions. Therefore, if you set the transaction isolation level to serializable, you must use the ALTER TABLE command to set INITRANS to at least 3. This parameter will cause Oracle to allocate sufficient storage in each block to record the history of recent transactions that accessed the block. Higher values should be used for tables that will undergo many transactions updating the same blocks.
    ?
    ??? read-only:
    ??????? 遵從事務級的讀一致性,僅僅能看見在本事務開始前由其它事務提交的更改。
    ??????? 不允許在本事務中進行DML操作。
    ??????? read only是serializable的子集。它們都避免了非重復讀和幻像。區別是在read only中是只讀;而在serializable中可以進行DML操作。
    ??????? Export with CONSISTENT = Y sets the transaction to read-only.
    ??????? read committed和serializable的區別和聯系:
    ?
    ??????? 事務1先于事務2開始,并保持未提交狀態。事務2想要修改正被事務1修改的行。事務2等待。如果事務1回滾,則事務2(不論是read committed還是 serializable方式)進行它想要做的修改。如果事務1提交,則當事務2是read committed方式時,進行它想要做的修改;當事務2是serializable方式時,失敗并報錯“Cannot serialize access”,因為事務2看不見事務1提交的修改,且事務2想在事務一修改的基礎上再做修改。具體見英文:Both read committed and serializable transactions use row-level locking, and both will wait if they try to change a row updated by an uncommitted concurrent transaction. The second transaction that tries to update a given row waits for the other transaction to commit or roll back and release its lock. If that other transaction rolls back, the waiting transaction (regardless of its isolation mode) can proceed to change the previously locked row, as if the other transaction had not existed. However, if the other (blocking) transaction commits and releases its locks, a read committed transaction proceeds with its intended update. A serializable transaction, however, fails with the error "Cannot serialize access", because the other transaction has committed a change that was made since the serializable transaction began.
    ?
    ??????? read committed和serializable可以在ORACLE并行服務器中使用。
    ?
    ??????? 關于SET TRANSACTION READ WRITE:read write和read committed 應該是一樣的。在讀方面,它們都避免了臟讀,但都無法實現重復讀。雖然沒有文檔說明read write在寫方面與read committed一致,但顯然它在寫的時候會加排他鎖以避免更新丟失。在加鎖的過程中,如果遇到待鎖定資源無法鎖定,應該是等待而不是放棄。這與read committed一致。
    ?
    ?
    語句級的讀一致性
    ?
    ??? ORACLE保證語句級的讀一致性,即一個語句所處理的數據集是在單一時間點上的數據集,這個時間點是這個語句開始的時間。
    ??? 一個語句看不見在它開始執行后提交的修改。
    ??? 對于DML語句,它看不見由自己所做的修改,即DML語句看見的是它本身開始執行以前存在的數據。
    ?
    事務級的讀一致性
    ?
    ??? 事務級的讀一致性保證了可重復讀,并保證不會出現幻像。
    ???
    設置隔離級別
    ?
    ??? 設置一個事務的隔離級別
    ??????? SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    ??????? SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    ??????? SET TRANSACTION READ ONLY;
    ?
    ??? 設置增個會話的隔離級別
    ??????? ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
    ??????? ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
    ?
    ?

    ?
    ?
    ?
    事務的隔離性研究

    ??? SQL 標準用三個必須在并行的事務之間避免的現象定義了四個級別的事務隔離。 這些不希望發生的現象是:
    ?
    ??? 臟讀(dirty reads)一個事務讀取了另一個未提交的并行事務寫的數據。
    ??? 不可重復讀(non-repeatable reads ) 一個事務重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務修改過。
    ??? 幻讀(phantom read ) 一個事務重新執行一個查詢,返回一套符合查詢條件的行,發現這些行因為其他最近提交的事務而發生了改變。

    ??? 這四種隔離級別和對應的行為在表Table 12-1中描述:
    ?
    Table 12-1? SQL事務隔離級別
    隔離級別
    臟讀
    (Dirty Read)
    不可重復讀
    (NonRepeatable Read)
    幻讀
    (Phantom Read)
    讀未提交(Read uncommitted)
    可能
    可能
    可能
    讀已提交(Read committed)
    不可能
    可能
    可能
    可重復讀(Repeatable read)
    不可能
    不可能
    可能
    可串行化(Serializable)
    不可能
    不可能
    不可能
    ?
    ??? 在 PostgreSQL 里,你可以請求四種可能的事務隔離級別中的任意一種。但是在內部,實際上只有兩種獨立的隔離級別,分別對應讀已提交可串行化。如果你選擇了讀未提交的級別,實際上你用的是讀已提交,在你選擇可重復的讀級別的時候,實際上你用的是可串行化,所以實際的隔離級別可能比你選擇的更嚴格。這是 SQL 標準允許的:四種隔離級別只定義了哪種現象不能發生,但是沒有定義那種現象一定發生。 PostgreSQL 只提供兩種隔離級別的原因是,這是把標準的隔離級別與多版本并發控制架構映射相關的唯一的合理方法。可用的隔離級別的行為在下面小節里描述。
    ?
    1、讀已提交隔離級別
    ?
    ??? 讀已提交(Read Committed) 是 PostgreSQL 里的缺省隔離級別。當一個事務運行在這個隔離級別時,一個 SELECT 查詢只能看到查詢開始之前提交的數據而永遠無法看到未提交的數據或者是在查詢執行時其他并行的事務提交做的改變。(不過 SELECT 的確看得見同一次事務中前面更新的結果。即使它們還沒提交也看得到) 實際上,一個 SELECT 查詢看到一個在該查詢開始運行的瞬間該數據庫的一個快照。 請注意兩個相鄰的 SELECT 命令可能看到不同的數據,哪怕它們是在同一個事務里,因為其它事務會在第一個SELECT執行的時候提交。
    ?
    ??? UPDATE、 DELETE或者 SELECT FOR UPDATE 在搜索目標行的時候的行為和SELECT 一樣:它們只能找到在命令開始的時候已經提交的行。不過,這樣的目標行在被找到的時候可能已經被其它并發的事務更新 (或者刪除,或者標記為更新的)。在這種情況下,即將進行的更新將等待第一個更新事務提交或者回滾 (如果它還在處理)。 如果第一個更新回滾,那么它的作用將被忽略,而第二個更新者將繼續更新最初發現的行。如果第一個更新者提交,那么如果第一個更新者刪除了該行,則第二個更新者將忽略該行,否則它將試圖在該行的已更新的版本上施加它的操作。系統將重新計算命令搜索條件(WHERE 子句),看看該行已更新的版本是否仍然符合搜索條件。如果是,則第二個更新繼續其操作,從該行的已更新版本開始。
    ?
    ??? 因為上面的規則,正在更新的命令可能會看到不一致的快照 —— 它們可以看到影響它們試圖更新的并發更新命令的效果,但是它們看不到那些命令對數據庫里其它行的作用。這樣的行為令讀已提交模式不適合用于哪種涉及復雜搜索條件的命令。不過,它對于簡單的情況而言是正確的。比如,假設我們用類似下面這樣的命令更新銀行余額:
    ?
    ??? BEGIN;
    ??? UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 12345;
    ??? UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 7534;
    ??? COMMIT;
    ??? 如果兩個并發事務試圖修改帳號 12345 的余額,那我們很明顯希望第二個事務是從帳戶行的已經更新過的版本上進行更新。因為每個命令只是影響一個已經決定了的行,因此讓它看到更新后的版本不會導致任何不一致的問題。
    ?
    ??? 因為在讀已提交模式里,每個新的命令都是從一個新的快照開始的,而這個快照包含所有到該時刻為止已經提交的事務,因此同一個事務里的后面的命令將看到任何已提交的并發事務的效果。 這里要考慮的問題是我們在一個命令里是否看到數據庫里絕對一致的視圖。
    ?
    ??? 讀已提交模式提供的部分事務隔離對于許多應用而言是足夠的,并且這個模式速度快,使用簡單。不過,對于做復雜查詢和更新的應用,可能需要保證數據庫有比讀已提交模式提供的更加嚴格的一致性視圖。
    ?
    2、可串行化隔離級別

    ??? 可串行化(Serializable) 級別提供最嚴格的事務隔離。這個級別模擬串行的事務執行,就好象事務將被一個接著一個那樣串行的,而不是并行的執行。不過,使用這個級別的應用必須準備在串行化失敗的時候重新發動事務。
    ?
    ??? 當一個事務處于可串行化級別,一個 SELECT 查詢只能看到在事務開始之前提交的數據而永遠看不到未提交的數據或事務執行中其他并行事務提交的修改。(不過,SELECT 的確看得到同一次事務中前面的更新的效果。即使事務還沒有提交也一樣) 這個行為和讀已提交級別是不太一樣,它的 SELECT 看到的是該事務開始時的快照,而不是該事務內部當前查詢開始時的快照。這樣,一個事務內部后面的 SELECT 命令總是看到同樣的數據。
    ?
    ??? UPDATE、DELETE和 SELECT FOR UPDATE 在搜索目標行上的行為和 SELECT 一樣:它們將只尋找在事務開始的時候已經提交的目標行。但是,這樣的目標行在被發現的時候可能已經被另外一個并發的事務更新了(或者是刪除或者是標記為更新)。在這種情況下,可串行化的事務將等待第一個正在更新的事務提交或者回滾 (如果它仍然在處理中)。 如果第一個更新者回滾,那么它的影響將被忽略, 而這個可串行化的就可以繼續更新它最初發現的行。但是如果第一個更新者提交了 (并且實際上更新或者刪除了該行,而不只是為更新選中它) 那么可串行化事務將回滾,并返回下面信息:
    ??? ERROR:? Can't serialize access due to concurrent update
    ??? 因為一個可串行化的事務在可串行化事務開始之后不能更改被其他事務更改過的行。
    ?
    ??? 當應用收到這樣的錯誤信息時,它應該退出當前的事務然后從頭開始重新進行整個事務。第二次運行時,該事務看到的前一次提交的修改是該數據庫初始的樣子中的一部分, 所以把新版本的行作為新事務更新的起點不會有邏輯沖突。
    ?
    ??? 請注意只有更新事務才需要重試,只讀事務從來沒有串行化沖突
    ?
    ??? 可串行化事務級別提供了嚴格的保證:每個事務都看到一個完全一致的數據庫的視圖。不過,如果并行更新令數據庫不能維持串行執行的樣子,那么應用必須準備重試事務。因為重做復雜的事務的開銷可能是非常可觀的,所以我們只建議在更新命令中包含足夠復雜的邏輯,在讀已提交級別中可能導致錯誤的結果的情況下才使用。最常見的是,可串行化模式只是在這樣的情況下是必要的:一個事務連續做若干個命令, 而這幾個命令必須看到數據庫完全一樣的視圖。
    ?
    3、可串行化隔離與真正的可串行化之比較

    ??? 執行的“可串行化”的直觀含義(以及數學定義)是兩個成功提交的并發事務將顯得好像嚴格地串行執行一樣,一個跟著一個 —— 盡管我們可能無法預期哪個首先執行。我們必須明白,禁止那些在 Table 12-1 里面列出的行為并不能保證真正的可串行化。并且,實際上 PostgreSQL 的可串行化模式并不保證在這種含義下的可串行化。舉例來說,假設一個表 mytab,最初包含
    ?
    class | value
    -------+-------
    ???? 1 |??? 10
    ???? 1 |??? 20
    ???? 2 |?? 100
    ???? 2 |?? 200
    ?
    ??? 假設可串行化事務 A 計算: SELECT SUM(value) FROM mytab WHERE class = 1; ?然后把結果(30)作為 value 到表中,class = 2。 同時,一個并發的可串行化的事務 B 進行下面計算: SELECT SUM(value) FROM mytab WHERE class = 2; ?并且獲取結果 300,然后它插入一行新行,class = 1
    ?
    ??? 然后兩個事務都提交。所有列出的禁止行為都不會發生,但是我們拿到的結果是不可能在任何一種串行執行下看到的。如果 A 在 B 之前執行,B 應該計算出總和 330,而不是 300,如果是另外一種順序,那么 A 計算出的總和也會不同。
    ?
    ??? 為了保證真正數學上的可串行化,一個數據庫系統必須強制謂詞鎖定, 這就意味著一個事務不能插入或者更改這樣的數據行:這個數據行的數據匹配另外一個并發事務的 WHERE 條件。 比如,一旦事務 A 執行了查詢 SELECT ... WHERE class = 1,那么一個謂詞鎖定系統將禁止事務 B 插入任何 class 為 1 的新行,直到 A 提交。 實際上,一個謂詞鎖定系統避免了幻讀,方法是約束寫入的東西,而 MVCC 避免幻讀的方法是約束它讀取的東西。這樣的鎖系統實現起來非常復雜,并且執行起來代價高昂,因為每個會話都必須要知道每個并發事務的每個查詢的執行細節。并且這樣大量的開銷在大部分情況下都是浪費掉的,因為在實際情況下大部分應用都不做會導致問題的這種事情。(當然,上面的例子是靜心設計的,不能代表真實的軟件。) 因此,PostgreSQL 并未實現謂詞鎖定,而就我們所知,沒有其它的生產中的 DBMS 實現了這個。
    ?
    ??? 在那些非串行化執行真的可能有危險的場合,可以通過使用明確的鎖定來避免問題的發生。
    ?
    ?
    posted on 2009-04-21 22:45 decode360 閱讀(639) 評論(0)  編輯  收藏 所屬分類: 12.Certified
    主站蜘蛛池模板: 亚洲国产精品免费观看 | 国产精品免费看久久久久| 亚洲av无一区二区三区| 亚洲性在线看高清h片| 成人免费的性色视频| 老湿机一区午夜精品免费福利| 亚洲第一中文字幕| 天天摸夜夜摸成人免费视频| 久久毛片免费看一区二区三区| 亚洲成人福利在线| 国产成人精品日本亚洲专区| 精品免费人成视频app| 成人免费视频一区二区| 亚洲国产日韩在线成人蜜芽| 亚洲人成无码www久久久| 无码人妻精品中文字幕免费东京热| 黄网站色成年片大免费高清| 亚洲小说图片视频| 亚洲人成中文字幕在线观看| 国产精品四虎在线观看免费 | 中国一级全黄的免费观看| 亚洲精品美女网站| 亚洲AV午夜福利精品一区二区| 在线观看91精品国产不卡免费| 伊人久久免费视频| AAAAA级少妇高潮大片免费看| 久久乐国产综合亚洲精品| 久久精品国产精品亚洲色婷婷| 亚洲?V乱码久久精品蜜桃 | 久久久无码精品亚洲日韩按摩 | 亚洲黄色激情视频| 久久亚洲AV成人无码国产| 在线亚洲人成电影网站色www| 国产乱色精品成人免费视频| 免费观看美女用震蛋喷水的视频 | 亚洲无人区码一二三码区别图片| 亚洲成a人片77777老司机| 亚洲人成中文字幕在线观看| 亚洲国产精品尤物YW在线观看| 成人免费无码精品国产电影| 最近免费中文字幕大全|