日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate 事物隔离级别 深入探究

發(fā)布時(shí)間:2023/12/13 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate 事物隔离级别 深入探究 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

一、數(shù)據(jù)庫事務(wù)的定義

二、數(shù)據(jù)庫事務(wù)并發(fā)可能帶來的問題

三、數(shù)據(jù)庫事務(wù)隔離級別

四、使用Hibernate設(shè)置數(shù)據(jù)庫隔離級別

五、使用悲觀鎖解決事務(wù)并發(fā)問題

六、使用樂觀鎖解決事務(wù)并發(fā)問題

?

??Hibernate事務(wù)與并發(fā)問題處理(樂觀鎖與悲觀鎖)

一、數(shù)據(jù)庫事務(wù)的定義

  數(shù)據(jù)庫事務(wù)(Database Transaction) ,是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作。事務(wù)處理可以確保除非事務(wù)性單元內(nèi)的所有操作都成功完成,否則不會(huì)永久更新面向數(shù)據(jù)的資源。通過將一組相關(guān)操作組合為一個(gè)要么全部成功要么全部失敗的單元,可以簡化錯(cuò)誤恢復(fù)并使應(yīng)用程序更加可靠。一個(gè)邏輯工作單元要成為事務(wù),必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。?

  1. 原子性(atomic),事務(wù)必須是原子工作單元;對于其數(shù)據(jù)修改,要么全都執(zhí)行,要么全都不執(zhí)行

  2. 一致性(consistent),事務(wù)在完成時(shí),必須使所有的數(shù)據(jù)都保持一致狀態(tài)。

  3. 隔離性(insulation),由并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離。

  4. 持久性(Duration),事務(wù)完成之后,它對于系統(tǒng)的影響是永久性的。

二、數(shù)據(jù)庫事務(wù)并發(fā)可能帶來的問題?

  如果沒有鎖定且多個(gè)用戶同時(shí)訪問一個(gè)數(shù)據(jù)庫,則當(dāng)他們的事務(wù)同時(shí)使用相同的數(shù)據(jù)時(shí)可能會(huì)發(fā)生問題。由于并發(fā)操作帶來的數(shù)據(jù)不一致性包括:丟失數(shù)據(jù)修改、讀”臟”數(shù)據(jù)(臟讀)、不可重復(fù)讀、產(chǎn)生幽靈數(shù)據(jù):

假設(shè)數(shù)據(jù)庫中有如下一張表:

  1. 第一類丟失更新(lost update): 在完全未隔離事務(wù)的情況下,兩個(gè)事物更新同一條數(shù)據(jù)資源,某一事物異常終止,回滾造成第一個(gè)完成的更新也同時(shí)丟失。

  在T1時(shí)刻開啟了事務(wù)1,T2時(shí)刻開啟了事務(wù)2,在T3時(shí)刻事務(wù)1從數(shù)據(jù)庫中取出了id="402881e535194b8f0135194b91310001"的數(shù)據(jù),T4時(shí)刻事務(wù)2取出了同一條數(shù)據(jù),T5時(shí)刻事務(wù)1將age字段值更新為30,T6時(shí)刻事務(wù)2更新age為35并提交了數(shù)據(jù),但是T7事務(wù)1回滾了事務(wù)age最后的值依然為20,事務(wù)2的更新丟失了,這種情況就叫做"第一類丟失更新(lost update)"。

  2. 臟讀(dirty read):如果第二個(gè)事務(wù)查詢到第一個(gè)事務(wù)還未提交的更新數(shù)據(jù),形成臟讀。

  在T1時(shí)刻開啟了事務(wù)1,T2時(shí)刻開啟了事務(wù)2,在T3時(shí)刻事務(wù)1從數(shù)據(jù)庫中取出了id="402881e535194b8f0135194b91310001"的數(shù)據(jù),在T5時(shí)刻事務(wù)1將age的值更新為30,但是事務(wù)還未提交,T6時(shí)刻事務(wù)2讀取同一條記錄,獲得age的值為30,但是事務(wù)1還未提交,若在T7時(shí)刻事務(wù)1回滾了事務(wù)2的數(shù)據(jù)就是錯(cuò)誤的數(shù)據(jù)(臟數(shù)據(jù)),這種情況叫做"?臟讀(dirty read)"。

  3. 虛讀(phantom read):一個(gè)事務(wù)執(zhí)行兩次查詢,第二次結(jié)果集包含第一次中沒有或者某些行已被刪除,造成兩次結(jié)果不一致,只是另一個(gè)事務(wù)在這兩次查詢中間插入或者刪除了數(shù)據(jù)造成的。

  在T1時(shí)刻開啟了事務(wù)1,T2時(shí)刻開啟了事務(wù)2,T3時(shí)刻事務(wù)1從數(shù)據(jù)庫中查詢所有記錄,記錄總共有一條,T4時(shí)刻事務(wù)2向數(shù)據(jù)庫中插入一條記錄,T6時(shí)刻事務(wù)2提交事務(wù)。T7事務(wù)1再次查詢數(shù)據(jù)數(shù)據(jù)時(shí),記錄變成兩條了。這種情況是"虛讀(phantom read)"。

  4. 不可重復(fù)讀(unrepeated read):一個(gè)事務(wù)兩次讀取同一行數(shù)據(jù),結(jié)果得到不同狀態(tài)結(jié)果,如中間正好另一個(gè)事務(wù)更新了該數(shù)據(jù),兩次結(jié)果相異,不可信任。

  在T1時(shí)刻開啟了事務(wù)1,T2時(shí)刻開啟了事務(wù)2,在T3時(shí)刻事務(wù)1從數(shù)據(jù)庫中取出了id="402881e535194b8f0135194b91310001"的數(shù)據(jù),此時(shí)age=20,T4時(shí)刻事務(wù)2查詢同一條數(shù)據(jù),T5事務(wù)2更新數(shù)據(jù)age=30,T6時(shí)刻事務(wù)2提交事務(wù),T7事務(wù)1查詢同一條數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)與第一次不一致。這種情況就是"不可重復(fù)讀(unrepeated read)"。

  5. 第二類丟失更新(second lost updates):是不可重復(fù)讀的特殊情況,如果兩個(gè)事務(wù)都讀取同一行,然后兩個(gè)都進(jìn)行寫操作,并提交,第一個(gè)事務(wù)所做的改變就會(huì)丟失。

  在T1時(shí)刻開啟了事務(wù)1,T2時(shí)刻開啟了事務(wù)2,T3時(shí)刻事務(wù)1更新數(shù)據(jù)age=25,T5時(shí)刻事務(wù)2更新數(shù)據(jù)age=30,T6時(shí)刻提交事務(wù),T7時(shí)刻事務(wù)2提交事務(wù),把事務(wù)1的更新覆蓋了。這種情況就是"第二類丟失更新(second lost updates)"。

?

三、數(shù)據(jù)庫事務(wù)隔離級別

為了解決數(shù)據(jù)庫事務(wù)并發(fā)運(yùn)行時(shí)的各種問題數(shù)據(jù)庫系統(tǒng)提供四種事務(wù)隔離級別:
1. Serializable 串行化
2. Repeatable Read 可重復(fù)讀
3. Read Commited 可讀已提交
4. Read Uncommited 可讀未提交

隔離級別與并發(fā)性能的關(guān)系:?

每一個(gè)隔離級別可以解決的問題:

?

四、使用Hibernate設(shè)置數(shù)據(jù)庫隔離級別

在Hibernate的配置文件中可以顯示的配置數(shù)據(jù)庫事務(wù)隔離級別。每一個(gè)隔離級別用一個(gè)整數(shù)表示:

8 - Serializable 串行化
4 - Repeatable Read 可重復(fù)讀
2 - Read Commited 可讀已提交
1 - Read Uncommited 可讀未提交

在hibernate.cfg.xml中使用hibernate.connection.isolation參數(shù)配置數(shù)據(jù)庫事務(wù)隔離級別。

?

五、使用悲觀鎖解決事務(wù)并發(fā)問題

  悲觀鎖,正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個(gè)數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制(也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù))。

  一個(gè)典型的依賴數(shù)據(jù)庫的悲觀鎖調(diào)用:select * from account where name=”Erica” for update這條 sql 語句鎖定了 account 表中所有符合檢索條件( name=”Erica” )的記錄。本次事務(wù)提交之前(事務(wù)提交時(shí)會(huì)釋放事務(wù)過程中的鎖),外界無法修改這些記錄。悲觀鎖,也是基于數(shù)據(jù)庫的鎖機(jī)制實(shí)現(xiàn)。

在Hibernate使用悲觀鎖十分容易,但實(shí)際應(yīng)用中悲觀鎖是很少被使用的,因?yàn)樗蟠笙拗屏瞬l(fā)性:

圖為Hibernate3.6的幫助文檔Session文檔的get方法截圖,可以看到get方法第三個(gè)參數(shù)"lockMode"或"lockOptions",注意在Hibernate3.6以上的版本中"LockMode"已經(jīng)不建議使用。方法的第三個(gè)參數(shù)就是用來設(shè)置悲觀鎖的,使用第三個(gè)參數(shù)之后,我們每次發(fā)送的SQL語句都會(huì)加上"for update"用于告訴數(shù)據(jù)庫鎖定相關(guān)數(shù)據(jù)。

LockMode參數(shù)選擇該選項(xiàng),就會(huì)開啟悲觀鎖。

  T1,T2時(shí)刻取款事務(wù)和轉(zhuǎn)賬事務(wù)分別開啟,T3事務(wù)查詢ACCOUNTS表的數(shù)據(jù)并用悲觀鎖鎖定,T4轉(zhuǎn)賬事務(wù)也要查詢同一條數(shù)據(jù),數(shù)據(jù)庫發(fā)現(xiàn)該記錄已經(jīng)被前一個(gè)事務(wù)使用悲觀鎖鎖定了,然后讓轉(zhuǎn)賬事務(wù)等待直到取款事務(wù)提交。T6時(shí)刻取款事務(wù)提交,T7時(shí)刻轉(zhuǎn)賬事務(wù)獲取數(shù)據(jù)。

?

六、使用樂觀鎖解決事務(wù)并發(fā)問題

  相對悲觀鎖而言,樂觀鎖機(jī)制采取了更加寬松的加鎖機(jī)制。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機(jī)制實(shí)現(xiàn),以保證操作最大程度的獨(dú)占性。但隨之而來的就是數(shù)據(jù)庫性能的大量開銷,特別是對長事務(wù)而言,這樣的開銷往往無法承受。樂觀鎖機(jī)制在一定程度上解決了這個(gè)問題。樂觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個(gè)"version"字段來實(shí)現(xiàn)。
  樂觀鎖的工作原理:讀取出數(shù)據(jù)時(shí),將此版本號一同讀出,之后更新時(shí),對此版本號加一。此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。

Hibernate為樂觀鎖提供了3中實(shí)現(xiàn):

1. 基于version

2. 基于timestamp

3. 為遺留項(xiàng)目添加添加樂觀鎖?

配置基于version的樂觀鎖:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<!-- version標(biāo)簽用于指定表示版本號的字段信息 -->
<version name="version" column="version" type="integer"></version>

<property name="name" column="name" type="string"></property>

</class>
</hibernate-mapping>

配置基于timestamp的樂觀鎖:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<!-- timestamp標(biāo)簽用于指定表示版本號的字段信息 -->
<timestamp name="updateDate" column="updateDate"></timestamp>

<property name="name" column="name" type="string"></property>

</class>
</hibernate-mapping>

遺留項(xiàng)目,由于各種原因無法為原有的數(shù)據(jù)庫添加"version"或"timestamp"字段,這時(shí)不可以使用上面兩種方式配置樂觀鎖,Hibernate為這種情況提供了一個(gè)"optimisitic-lock"屬性,它位于<class>標(biāo)簽上:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people" optimistic-lock="all">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<property name="name" column="name" type="string"></property>
</class>
</hibernate-mapping>

將該屬性的值設(shè)置為all,讓該記錄所有的字段都為版本控制信息。

轉(zhuǎn)載于:https://www.cnblogs.com/jiligalaer/p/3990369.html

總結(jié)

以上是生活随笔為你收集整理的Hibernate 事物隔离级别 深入探究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。