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

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

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

    jinfeng_wang

    G-G-S,D-D-U!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

     

    5.1.4 理解事務隔離級別

     

    問題

    The ANSI SQL standard defines the standard transaction isolation levels in terms of which of these phenomena are permissible:

    ANSI SQL分別針對以下可能出現的問題,定義了不同的標準事務隔離級別。

     

    Lost update—Two transactions both update a row and then the second transaction aborts, causing both changes to be lost. This occurs in systems that don’t implement any locking. The concurrent transactions aren’t isolated.

    更新丟失-兩個事務都同時更新一行數據,但是第二個事務卻中途失敗退出,導致對數據的兩個修改都失效了。這是因為系統沒有執行任何的鎖操作,因此并發事務并沒有被隔離開來。

     

    Dirty read—One transaction reads changes made by another transaction that hasn’t yet been committed. This is very dangerous, because those changes might later be rolled back.

    臟讀取-一個事務開始讀取了某行數據,但是另外一個事務已經更新了此數據但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都可能會被回滾。

     

    Unrepeatable read—A transaction reads a row twice and reads different state each time. For example, another transaction may have written to the row, and committed, between the two reads.

    不可重復讀-一個事務對同一行數據重復讀取兩次,但是卻得到了不同的結果。例如,在兩次讀取的中途,有另外一個事務對該行數據進行了修改,并提交。

     

    Second lost updates problem—A special case of an unrepeatable read. Imagine that two concurrent transactions both read a row, one writes to it and commits, and then the second writes to it and commits. The changes made by the first writer are lost.

    兩次更新問題-無法重復讀取的特例。有兩個并發事務同時讀取同一行數據,然后其中一個對它進行修改提交,而另一個也是修改提交。這就會造成第一次寫操作失效。

     

    Phantom read—A transaction executes a query twice, and the second result set includes rows that weren’t visible in the first result set. (It need not necessarily be exactly the same query.) This situation is caused by another transaction inserting new rows between the execution of the two queries.

    讀取幻影數據-事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據(這里并不要求兩次查詢的sql語句相同)。這是因為在兩次查詢過程中有另外一個事務插入數據造成的。

     

    事務隔離級別

     

    The standard isolation levels are defined by the ANSI SQL standard but aren’t particular to SQL databases. JTA defines the same isolation levels, and you’ll use these levels to declare your desired transaction isolation later:

    雖然ANSI SQL定義了標準的事務隔離級別,但是不聽的SQL數據庫的實現則是不同的。JTA定義了同樣的事務隔離級別,你可以在按照你的要求使用它們:

     

    Read uncommitted—Permits dirty reads but not lost updates. One transaction may not write to a row if another uncommitted transaction has already written to it. Any transaction may read any row, however. This isolation level may be implemented using exclusive write locks.

    未授權讀取-允許臟讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個數據則不允許同時寫。但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

     

    Read committed—Permits unrepeatable reads but not dirty reads. This may be achieved using momentary shared read locks and exclusive write locks. Reading transactions don’t block other transactions from accessing a row. However, an uncommitted writing transaction blocks all other transactions from accessing the row.

    授權讀取-允許不可重復讀取,但不允許臟讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

     

    Repeatable read—Permits neither unrepeatable reads nor dirty reads. Phantom reads may occur. This may be achieved using shared read locks and exclusive write locks. Reading transactions block writing transactions (but not other reading transactions), and writing transactions block all other transactions.

    可重復讀取-禁止不可重復讀取和臟讀取,但是有時可能出現幻影數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

     

    Serializable—Provides the strictest transaction isolation. It emulates serial transaction execution, as if transactions had been executed one after another, serially, rather than concurrently. Serializability may not be implemented using only row-level locks; there must be another mechanism that prevents a newly inserted row from becoming visible to a transaction that has already executed a query that would return the row.

    序列化-提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個的執行,但不能并發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

     

    5.1.5 選擇正確的事務隔離級別

    First, you eliminate the read uncommitted isolation level. It’s extremely dangerous to use one transaction’s uncommitted changes in a different transaction. The rollback or failure of one transaction would affect other concurrent transactions. Rollback of the first transaction could bring other transactions down with it, or perhaps even cause them to leave the database in an inconsistent state. It’s possible that changes made by a transaction that ends up being rolled back could be committed anyway, since they could be read and then propagated by another transaction that is successful!

    首先,必須排除“未授權讀取”,因為在多個事務之間使用它將會是非常危險的。事務的回滾操作或失敗將會影響到其他并發事務。第一個事務的回滾將會完全將其他事務的操作清除,甚至使數據庫處在一個不一致的狀態。很可能一個已回滾為結束的事務對數據的修改最后卻修改提交了,因為“未授權讀取”允許其他事務讀取數據,最后整個錯誤狀態在其他事務之間傳播開來。

     

    Second, most applications don’t need serializable isolation (phantom reads aren’t usually a problem), and this isolation level tends to scale poorly. Few existing applications use serializable isolation in production; rather, they use pessimistic locks, which effectively forces a serialized execution of operations in certain situations.

    其次,絕大部分應用都無需使用“序列化”隔離(一般來說,讀取幻影數據并不是一個問題),此隔離級別也難以測量。目前使用序列化隔離的應用中,一般都使用的悲觀鎖,這樣強行使得所有事務都序列化執行。

     

    This leaves you a choice between read committed and repeatable read. Let’s first consider repeatable read. This isolation level eliminates the possibility that one transaction could overwrite changes made by another concurrent transaction (the second lost updates problem) if all data access is performed in a single atomic database transaction. This is an important issue, but using repeatable read isn’t the only way to resolve it.

    剩下的也就是在“授權讀取”和“可重復讀取”之間選擇了。我們先考慮可重復讀取。如果所有的數據訪問都是在統一的原子數據庫事務中,此隔離級別將消除一個事務在另外一個并發事務過程中覆蓋數據的可能性(第二個事務更新丟失問題)。這是一個非常重要的問題,但是使用可重復讀取并不是解決問題的唯一途徑。

     

    Let’s assume you’re using versioned data, something that Hibernate can do for you automatically. The combination of the (mandatory) Hibernate first-level session cache and versioning already gives you most of the features of repeatable read isolation. In particular, versioning prevents the second lost update problem, and the first-level session cache ensures that the state of the persistent instances loaded by one transaction is isolated from changes made by other transactions. So, read committed isolation for all database transactions would be acceptable if you use versioned data.

    讓我們假設你使用了“版本數據”,hibernate會為你自動使用版本數據。Hibernate的一級session緩存和版本數據已經喂你提供了“可重復讀取隔離” 絕大部分的特性。特別是,版本數據可以防止二次更新丟失的問題,一級session緩存可以保證持久載入數據的狀態與其他事務對數據的修改隔離開來,因此如果你使用對所有的數據庫事務采用授權讀取隔離和版本數據是行得通的。

     

    Repeatable read provides a bit more reproducibility for query result sets (only for the duration of the database transaction), but since phantom reads are still possible, there isn’t much value in that. (It’s also not common for web applications to query the same table twice in a single database transaction.)

    “可重復讀取”為數據庫查詢提供了更好的效率(僅對那些長時間的數據庫事務),但是由于幻影讀取依然存在,因此并沒必要使用它(對于Web應用來說,一般也很少在一個數據庫事務中對同一個表查詢兩次)。

     

    You also have to consider the (optional) second-level Hibernate cache. It can provide the same transaction isolation as the underlying database transaction, but it might even weaken isolation. If you’re heavily using a cache concurrency strategy for the second-level cache that doesn’t preserve repeatable read semantics (for example, the read-write and especially the nonstrict-read-write strategies, both discussed later in this chapter), the choice for a default isolation level is easy: You can’t achieve repeatable read anyway, so there’s no point slowing down the database. On the other hand, you might not be using second-level caching for critical classes, or you might be using a fully transactional cache that provides repeatable read isolation. Should you use repeatable read in this case? You can if you like, but it’s probably not worth the performance cost.

    你也可以同時考慮選擇使用hibernate的二級緩存,它可以如同底層的數據庫事務一樣提供相同的事務隔離,但是它可能弱化隔離。假如你大量在二級緩存使用緩存并發策略,它并不提供重復讀取語義(例如,后面章節中將要討論的讀寫,特別是非嚴格讀寫),很容易可以選擇默認的隔離級別:因為你無論如何都無法實現“可重復讀取”,因此就更無必要拖慢數據庫了。另一方面,你可能對關鍵類不采用二級緩存,或者采用一個完全的事務緩存,提供“可重復讀取隔離”。那么在你的業務中需要使用到“可重復讀取”嗎?如果你喜歡,你當然可以那樣做,但更多的時候并沒有必要花費這個代價。

     

    5.1.6  hibernate中設置隔離級別l

    Hibernate will then set this isolation level on every JDBC connection obtained from a connection pool before starting a transaction. The sensible values for this option are as follows (you can also find them as constants in java.sql.Connection):

    1—Read uncommitted isolation

    2—Read committed isolation

    4—Repeatable read isolation

    8—Serializable isolation

    Note that Hibernate never changes the isolation level of connections obtained from a datasource provided by the application server in a managed environment. You may change the default isolation using the configuration of your application server.

    Hibernte將會在啟動事務之前,為從數據庫鏈接池中取得的每一個connection設置隔離級別。其常量值如下(你可以在java.sql.connection中常量中找到):

    1-未授權讀取隔離

    2-授權讀取隔離

    4-可重復讀取隔離

    8-序列化隔離

    注意:hibernate不會對從應用服務器管理的數據源取得的數據庫連接的隔離級別進行設置。你需要在你的應用服務器進行配置,修改其默認的隔離級別。

     

     

    5.1.7 使用悲觀鎖

    Locking is a mechanism that prevents concurrent access to a particular item of data. When one transaction holds a lock on an item, no concurrent transaction can read and/or modify this item. A lock might be just a momentary lock, held while the item is being read, or it might be held until the completion of the transaction. A pessimistic lock is a lock that is acquired when an item of data is read and that is held until transaction completion.

    鎖是用來防止并發訪問同一數據的機制。當一個事務對一個數據擁有了鎖,那么其他并發事務則無法對它進行讀或者寫。這里的鎖可以是瞬時的鎖,僅當在數據被讀取時存在,也可以時長期的,直到整個事務結束時釋放。悲觀鎖是指:它在數據被讀取時獲取,在事務結束時釋放。

     

    In read-committed mode (our preferred transaction isolation level), the database never acquires pessimistic locks unless explicitly requested by the application. Usually, pessimistic locks aren’t the most scalable approach to concurrency. However, in certain special circumstances, they may be used to prevent database-level deadlocks, which result in transaction failure. Some databases (Oracle and PostgreSQL, for example) provide the SQL SELECT...FOR UPDATE syntax to allow the use of explicit pessimistic locks. You can check the Hibernate Dialects to find out if your database supports this feature. If your database isn’t supported, Hibernate will always execute a normal SELECT without the FOR UPDATE clause.

    在“授權讀取”模式下(我們推薦的事務隔離級別),數據庫將永不使用悲觀鎖,除非應用程序特別的顯式生氣。通常,悲觀鎖是不適合大規模并發操作的。但是在某些特殊場合下,需要使用悲觀鎖,以防止那些會引起整個事務失敗的數據庫死鎖的發生。有些數據庫(例如OraclePostgreSQL)可以提供“sql select … for update”這樣的語法,讓用戶顯式的使用悲觀鎖。你 可以去查看hibernatedialect的文檔,確認你的數據庫是否支持此特性。如果你的數據庫不支持,那么hibernate就會僅僅執行普通的select語句,而不帶有for update字段。

     

    The Hibernate LockMode class lets you request a pessimistic lock on a particular item. In addition, you can use the LockMode to force Hibernate to bypass the cache layer or to execute a simple version check. You’ll see the benefit of these operations when we discuss versioning and caching.

    Hibernatelockmode類允許你為某個數據申請悲觀鎖,此外,你可以使用lockmode強制hibernate穿越其緩存層、或者執行簡單的版本校驗。從我們對版本數據和緩存的討論中了解這些操作的作用。

     

    Let’s see how to use LockMode. If you have a transaction that looks like this

    Transaction tx = session.beginTransaction();

    Category cat = (Category) session.get(Category.class, catId);

    cat.setName("New Name");

    tx.commit();

    then you can obtain a pessimistic lock as follows:

    Transaction tx = session.beginTransaction();

    Category cat =

    (Category) session.get(Category.class, catId, LockMode.UPGRADE);

    cat.setName("New Name");

    tx.commit();

    With this mode, Hibernate will load the Category using a SELECT...FOR UPDATE, thus locking the retrieved rows in the database until they’re released when the transaction ends.

    讓我們先看看如何使用lockmode。如果你有一個事務是這樣的:

    Transaction tx = session.beginTransaction();

    Category cat = (Category) session.get(Category.class, catId);

    cat.setName("New Name");

    tx.commit();

    那么你可以通過如下方法,獲得悲觀鎖。

    Transaction tx = session.beginTransaction();

    Category cat =

    (Category) session.get(Category.class, catId, LockMode.UPGRADE);

    cat.setName("New Name");

    tx.commit();

    使用lockmode.UPGRADEhibernate將會在載入Category時使用“select… for update”并鎖定數據,然后直到事務結束時,才會釋放鎖。

     

     

    Hibernate defines several lock modes:

    LockMode.NONE—Don’t go to the database unless the object isn’t in either cache.

    LockMode.READ—Bypass both levels of the cache, and perform a version check to verify that the object in memory is the same version that currently exists in the database.

    LockMode.UPDGRADE—Bypass both levels of the cache, do a version check (if applicable), and obtain a database-level pessimistic upgrade lock, if that is supported.

    LockMode.UPDGRADE_NOWAIT—The same as UPGRADE, but use a SELECT...FOR UPDATE NOWAIT on Oracle. This disables waiting for concurrent lock releases, thus throwing a locking exception immediately if the lock can’t be obtained.

            LockMode.WRITE—Is obtained automatically when Hibernate has written to a row in the current transaction (this is an internal mode; you can’t specify it explicitly).

    Hibernate定義了以下幾種lockmode

      LockMode.NONE-不訪問數據庫,除非該對象不在緩存中。

      LockMode.READ-穿越兩層緩存,進行版本校驗,以保證內存中的對象和數據庫中的版本相同。

      LockMode.UPGRADE-穿越兩次緩存,進行數據版本校驗,如果可以,則對數據庫級別加上悲觀更新鎖。

      LockMode.UPGRADE_NOWAIT-和UPGRADE相同,但是對Oracle使用select … for update no wait語句。如果當前數據被鎖,則無需等待,直接拋出異常。

      LockMode.WRITE-當hibernate在當前事務中寫一行數據時,會自動使用它(這是內部模式,你不該顯式的去使用)。

     

    By default, load() and get() use LockMode.NONE. LockMode.READ is most useful with

    Session.lock() and a detached object. For example:

    Item item = ... ;

    Bid bid = new Bid();

    item.addBid(bid);

    ...

    Transaction tx = session.beginTransaction();

    session.lock(item, LockMode.READ);

    tx.commit();

    This code performs a version check on the detached Item instance to verify that the database row wasn’t updated by another transaction since it was retrieved, before saving the new Bid by cascade (assuming that the association from Item to Bid has cascading enabled).

    默認情況下,load()get()使用LockMode.NONE,而LockMode.READ則更多的被session.lock和分離對象使用。例如:

    Item item = ... ;

    Bid bid = new Bid();

    item.addBid(bid);

    ...

    Transaction tx = session.beginTransaction();

    session.lock(item, LockMode.READ);

    tx.commit();

    這里的代碼在對新的bid級聯保存之前(假設在配置中允許級聯),對分離的Item實例進行了版本檢查,以校驗數據庫的數據從上次獲得以來未被其他事務更新。

     

    By specifying an explicit LockMode other than LockMode.NONE, you force Hibernate to bypass both levels of the cache and go all the way to the database. We think that most of the time caching is more useful than pessimistic locking, so we don’t use an explicit LockMode unless we really need it. Our advice is that if you have a professional DBA on your project, let the DBA decide which transactions require pessimistic locking once the application is up and running. This decision should depend on subtle details of the interactions between different transactions and can’t be guessed up front.

    通過顯式的聲明LockMode,而不是采用默認的LockMode.NONE,你可以強迫hibernate穿越兩層緩存,然后像直接訪問數據庫那樣行事。但是我們認為,在絕大部分情況下,緩存要比悲觀鎖有用的多,因此除非真的需要,我們并不建議顯式使用LockMode。我們的建議是,如果你的項目有一個專職的DBA,那么讓DBA在系統允許時決定哪個事務該采用悲觀鎖。這完全依賴于多個事務之間的底層細節,而不該在簡單的前臺猜測。

     

     

    posted on 2005-04-07 14:03 jinfeng_wang 閱讀(3229) 評論(0)  編輯  收藏 所屬分類: hibernate
    主站蜘蛛池模板: 中文字幕乱码免费看电影| 女人18毛片水真多免费播放| 久久精品a亚洲国产v高清不卡 | 一级毛片在线免费看| 亚洲国产成AV人天堂无码| 日本一道一区二区免费看| 人妻在线日韩免费视频| 亚洲天堂2016| 亚洲美女在线国产| 99爱在线精品免费观看| 一区二区免费国产在线观看| 91在线亚洲精品专区| 一本色道久久88综合亚洲精品高清| 国内精品免费在线观看| 亚洲av午夜电影在线观看| 久久精品国产亚洲av麻| 在线免费观看韩国a视频| 免费黄网站在线看| 麻豆安全免费网址入口| 亚洲精品视频在线免费| 亚洲精品无码久久毛片| 永久免费av无码不卡在线观看| 久久嫩草影院免费看夜色| 国产亚洲精aa在线看| 亚洲国语精品自产拍在线观看 | 中文字幕人成人乱码亚洲电影| 免费H网站在线观看的| 韩国免费a级作爱片无码| 亚洲精品白浆高清久久久久久| 久久久久噜噜噜亚洲熟女综合| 中文字幕亚洲精品无码| 亚洲一区二区三区在线观看蜜桃| 免费大片黄手机在线观看| 97视频免费在线| 久久久久久AV无码免费网站下载 | 亚洲人精品午夜射精日韩| 亚洲综合精品网站在线观看| 精品免费久久久久久久| 中国人免费观看高清在线观看二区 | 香蕉视频在线观看免费国产婷婷| 鲁大师在线影院免费观看|