Decode360's Blog

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

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評(píng)論 :: 0 Trackbacks
          ORACLE的隔離級(jí)別
          ???????????????? 作者: Parrotao
          ?
          隔離級(jí)別(isolation level)
          ?
          ??? 隔離級(jí)別定義了事務(wù)與事務(wù)之間的隔離程度。
          ??? 隔離級(jí)別與并發(fā)性是互為矛盾的:隔離程度越高,數(shù)據(jù)庫(kù)的并發(fā)性越差;隔離程度越低,數(shù)據(jù)庫(kù)的并發(fā)性越好。
          ??? ANSI/ISO SQL92標(biāo)準(zhǔn)定義了一些數(shù)據(jù)庫(kù)操作的隔離級(jí)別:
          ??????? 未提交讀(read uncommitted)
          ??????? 提交讀(read committed)
          ??????? 重復(fù)讀(repeatable read)
          ??????? 序列化(serializable)
          ?
          ??? 通過(guò)一些現(xiàn)象,可以反映出隔離級(jí)別的效果。這些現(xiàn)象有:
          ??? 更新丟失(lost update):當(dāng)系統(tǒng)允許兩個(gè)事務(wù)同時(shí)更新同一數(shù)據(jù)是,發(fā)生更新丟失。
          ??? 臟讀(dirty read):當(dāng)一個(gè)事務(wù)讀取另一個(gè)事務(wù)尚未提交的修改時(shí),產(chǎn)生臟讀。
          ??? 非重復(fù)讀(nonrepeatable read):同一查詢?cè)谕皇聞?wù)中多次進(jìn)行,由于其他提交事務(wù)所做的修改或刪除,每次返回不同的結(jié)果集,此時(shí)發(fā)生非重復(fù)讀。(A transaction rereads data it has previously read and finds that another committed transaction has modified or deleted the data.)
          ??? 幻像(phantom read):同一查詢?cè)谕皇聞?wù)中多次進(jìn)行,由于其他提交事務(wù)所做的插入操作,每次返回不同的結(jié)果集,此時(shí)發(fā)生幻像讀。(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.)
          ?
          ??? 下面是隔離級(jí)別及其對(duì)應(yīng)的可能出現(xiàn)或不可能出現(xiàn)的現(xiàn)象:
          ?
          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的隔離級(jí)別
          ?
          ??? ORACLE提供了SQL92標(biāo)準(zhǔn)中的read committed和serializable,同時(shí)提供了非SQL92標(biāo)準(zhǔn)的read-only。
          ?
          ??? read committed:
          ??????? 這是ORACLE缺省的事務(wù)隔離級(jí)別。
          ??????? 事務(wù)中的每一條語(yǔ)句都遵從語(yǔ)句級(jí)的讀一致性。
          ??????? 保證不會(huì)臟讀;但可能出現(xiàn)非重復(fù)讀和幻像。
          ?
          ??? serializable:
          ??????? 簡(jiǎn)單地說(shuō),serializable就是使事務(wù)看起來(lái)象是一個(gè)接著一個(gè)地順序地執(zhí)行。
          ??????? 僅僅能看見(jiàn)在本事務(wù)開(kāi)始前由其它事務(wù)提交的更改和在本事務(wù)中所做的更改。
          ??????? 保證不會(huì)出現(xiàn)非重復(fù)讀和幻像。
          ??????? Serializable隔離級(jí)別提供了read-only事務(wù)所提供的讀一致性(事務(wù)級(jí)的讀一致性),同時(shí)又允許DML操作。
          ?
          ??????? 如果有在serializable事務(wù)開(kāi)始時(shí)未提交的事務(wù)在serializable事務(wù)結(jié)束之前修改了serializable事務(wù)將要修改的行并進(jìn)行了提交,則serializable事務(wù)不會(huì)讀到這些變更,因此發(fā)生無(wú)法序列化訪問(wèn)的錯(cuò)誤。(換一種解釋方法:只要在serializable事務(wù)開(kāi)始到結(jié)束之間有其他事務(wù)對(duì)serializable事務(wù)要修改的東西進(jìn)行了修改并提交了修改,則發(fā)生無(wú)法序列化訪問(wèn)的錯(cuò)誤)
          ?
          ??????? 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, (并且修改在后來(lái)被提交而沒(méi)有回滾), then the DML statement fails. 返回的錯(cuò)誤是ORA-08177: Cannot serialize access for this transaction。
          ?
          ??????? ORACLE在數(shù)據(jù)塊中記錄最近對(duì)數(shù)據(jù)行執(zhí)行修改操作的N個(gè)事務(wù)的信息,目的是確定是否有在本事務(wù)開(kāi)始時(shí)未提交的事務(wù)修改了本事務(wù)將要修改的行。具體見(jià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:
          ??????? 遵從事務(wù)級(jí)的讀一致性,僅僅能看見(jiàn)在本事務(wù)開(kāi)始前由其它事務(wù)提交的更改。
          ??????? 不允許在本事務(wù)中進(jìn)行DML操作。
          ??????? read only是serializable的子集。它們都避免了非重復(fù)讀和幻像。區(qū)別是在read only中是只讀;而在serializable中可以進(jìn)行DML操作。
          ??????? Export with CONSISTENT = Y sets the transaction to read-only.
          ??????? read committed和serializable的區(qū)別和聯(lián)系:
          ?
          ??????? 事務(wù)1先于事務(wù)2開(kāi)始,并保持未提交狀態(tài)。事務(wù)2想要修改正被事務(wù)1修改的行。事務(wù)2等待。如果事務(wù)1回滾,則事務(wù)2(不論是read committed還是 serializable方式)進(jìn)行它想要做的修改。如果事務(wù)1提交,則當(dāng)事務(wù)2是read committed方式時(shí),進(jìn)行它想要做的修改;當(dāng)事務(wù)2是serializable方式時(shí),失敗并報(bào)錯(cuò)“Cannot serialize access”,因?yàn)槭聞?wù)2看不見(jiàn)事務(wù)1提交的修改,且事務(wù)2想在事務(wù)一修改的基礎(chǔ)上再做修改。具體見(jiàn)英文: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并行服務(wù)器中使用。
          ?
          ??????? 關(guān)于SET TRANSACTION READ WRITE:read write和read committed 應(yīng)該是一樣的。在讀方面,它們都避免了臟讀,但都無(wú)法實(shí)現(xiàn)重復(fù)讀。雖然沒(méi)有文檔說(shuō)明read write在寫(xiě)方面與read committed一致,但顯然它在寫(xiě)的時(shí)候會(huì)加排他鎖以避免更新丟失。在加鎖的過(guò)程中,如果遇到待鎖定資源無(wú)法鎖定,應(yīng)該是等待而不是放棄。這與read committed一致。
          ?
          ?
          語(yǔ)句級(jí)的讀一致性
          ?
          ??? ORACLE保證語(yǔ)句級(jí)的讀一致性,即一個(gè)語(yǔ)句所處理的數(shù)據(jù)集是在單一時(shí)間點(diǎn)上的數(shù)據(jù)集,這個(gè)時(shí)間點(diǎn)是這個(gè)語(yǔ)句開(kāi)始的時(shí)間。
          ??? 一個(gè)語(yǔ)句看不見(jiàn)在它開(kāi)始執(zhí)行后提交的修改。
          ??? 對(duì)于DML語(yǔ)句,它看不見(jiàn)由自己所做的修改,即DML語(yǔ)句看見(jiàn)的是它本身開(kāi)始執(zhí)行以前存在的數(shù)據(jù)。
          ?
          事務(wù)級(jí)的讀一致性
          ?
          ??? 事務(wù)級(jí)的讀一致性保證了可重復(fù)讀,并保證不會(huì)出現(xiàn)幻像。
          ???
          設(shè)置隔離級(jí)別
          ?
          ??? 設(shè)置一個(gè)事務(wù)的隔離級(jí)別
          ??????? SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
          ??????? SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
          ??????? SET TRANSACTION READ ONLY;
          ?
          ??? 設(shè)置增個(gè)會(huì)話的隔離級(jí)別
          ??????? ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
          ??????? ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
          ?
          ?

          ?
          ?
          ?
          事務(wù)的隔離性研究

          ??? SQL 標(biāo)準(zhǔn)用三個(gè)必須在并行的事務(wù)之間避免的現(xiàn)象定義了四個(gè)級(jí)別的事務(wù)隔離。 這些不希望發(fā)生的現(xiàn)象是:
          ?
          ??? 臟讀(dirty reads)一個(gè)事務(wù)讀取了另一個(gè)未提交的并行事務(wù)寫(xiě)的數(shù)據(jù)。
          ??? 不可重復(fù)讀(non-repeatable reads ) 一個(gè)事務(wù)重新讀取前面讀取過(guò)的數(shù)據(jù),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù)修改過(guò)。
          ??? 幻讀(phantom read ) 一個(gè)事務(wù)重新執(zhí)行一個(gè)查詢,返回一套符合查詢條件的行,發(fā)現(xiàn)這些行因?yàn)槠渌罱峤坏氖聞?wù)而發(fā)生了改變。

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

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

          ??? 執(zhí)行的“可串行化”的直觀含義(以及數(shù)學(xué)定義)是兩個(gè)成功提交的并發(fā)事務(wù)將顯得好像嚴(yán)格地串行執(zhí)行一樣,一個(gè)跟著一個(gè) —— 盡管我們可能無(wú)法預(yù)期哪個(gè)首先執(zhí)行。我們必須明白,禁止那些在 Table 12-1 里面列出的行為并不能保證真正的可串行化。并且,實(shí)際上 PostgreSQL 的可串行化模式并不保證在這種含義下的可串行化。舉例來(lái)說(shuō),假設(shè)一個(gè)表 mytab,最初包含
          ?
          class | value
          -------+-------
          ???? 1 |??? 10
          ???? 1 |??? 20
          ???? 2 |?? 100
          ???? 2 |?? 200
          ?
          ??? 假設(shè)可串行化事務(wù) A 計(jì)算: SELECT SUM(value) FROM mytab WHERE class = 1; ?然后把結(jié)果(30)作為 value 到表中,class = 2。 同時(shí),一個(gè)并發(fā)的可串行化的事務(wù) B 進(jìn)行下面計(jì)算: SELECT SUM(value) FROM mytab WHERE class = 2; ?并且獲取結(jié)果 300,然后它插入一行新行,class = 1
          ?
          ??? 然后兩個(gè)事務(wù)都提交。所有列出的禁止行為都不會(huì)發(fā)生,但是我們拿到的結(jié)果是不可能在任何一種串行執(zhí)行下看到的。如果 A 在 B 之前執(zhí)行,B 應(yīng)該計(jì)算出總和 330,而不是 300,如果是另外一種順序,那么 A 計(jì)算出的總和也會(huì)不同。
          ?
          ??? 為了保證真正數(shù)學(xué)上的可串行化,一個(gè)數(shù)據(jù)庫(kù)系統(tǒng)必須強(qiáng)制謂詞鎖定, 這就意味著一個(gè)事務(wù)不能插入或者更改這樣的數(shù)據(jù)行:這個(gè)數(shù)據(jù)行的數(shù)據(jù)匹配另外一個(gè)并發(fā)事務(wù)的 WHERE 條件。 比如,一旦事務(wù) A 執(zhí)行了查詢 SELECT ... WHERE class = 1,那么一個(gè)謂詞鎖定系統(tǒng)將禁止事務(wù) B 插入任何 class 為 1 的新行,直到 A 提交。 實(shí)際上,一個(gè)謂詞鎖定系統(tǒng)避免了幻讀,方法是約束寫(xiě)入的東西,而 MVCC 避免幻讀的方法是約束它讀取的東西。這樣的鎖系統(tǒng)實(shí)現(xiàn)起來(lái)非常復(fù)雜,并且執(zhí)行起來(lái)代價(jià)高昂,因?yàn)槊總€(gè)會(huì)話都必須要知道每個(gè)并發(fā)事務(wù)的每個(gè)查詢的執(zhí)行細(xì)節(jié)。并且這樣大量的開(kāi)銷在大部分情況下都是浪費(fèi)掉的,因?yàn)樵趯?shí)際情況下大部分應(yīng)用都不做會(huì)導(dǎo)致問(wèn)題的這種事情。(當(dāng)然,上面的例子是靜心設(shè)計(jì)的,不能代表真實(shí)的軟件。) 因此,PostgreSQL 并未實(shí)現(xiàn)謂詞鎖定,而就我們所知,沒(méi)有其它的生產(chǎn)中的 DBMS 實(shí)現(xiàn)了這個(gè)。
          ?
          ??? 在那些非串行化執(zhí)行真的可能有危險(xiǎn)的場(chǎng)合,可以通過(guò)使用明確的鎖定來(lái)避免問(wèn)題的發(fā)生。
          ?
          ?
          posted on 2009-04-21 22:45 decode360 閱讀(640) 評(píng)論(0)  編輯  收藏 所屬分類: 12.Certified
          主站蜘蛛池模板: 城固县| 开封县| 略阳县| 开原市| 玉屏| 通渭县| 珠海市| 赫章县| 包头市| 阳新县| 石阡县| 那坡县| 阳西县| 班戈县| 台南市| 怀仁县| 钦州市| 平原县| 六盘水市| 黎平县| 岳阳县| 营口市| 健康| 韩城市| 尉氏县| 曲麻莱县| 清苑县| 崇信县| 乐昌市| 庄河市| 阿克陶县| 白朗县| 浦城县| 洪洞县| 南雄市| 武山县| 满洲里市| 胶南市| 定安县| 璧山县| 佛坪县|