事務(wù)、數(shù)據(jù)庫事務(wù)毫玖、事務(wù)隔離級別掀虎、鎖的簡單總結(jié)

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

1付枫、事務(wù)是作為單個(gè)邏輯工作單元執(zhí)行的一系列操作烹玉。可以是一條SQL語句也可以是多條SQL語句阐滩。

2春霍、事務(wù)具有四個(gè)特性

原子性(Atomicity):事務(wù)中的全部操作在數(shù)據(jù)庫中是不可分割的,要么全部完成叶眉,要么均不執(zhí)行址儒。

一致性(Consistency):幾個(gè)并行執(zhí)行的事務(wù),其執(zhí)行結(jié)果必須與按某一順序串行執(zhí)行的結(jié)果相一致衅疙。

隔離性(Isolation):事務(wù)的執(zhí)行不受其他事務(wù)的干擾莲趣,事務(wù)執(zhí)行的中間結(jié)果對其他事務(wù)必須是透明的。

持久性(Durability):對于任意已提交事務(wù)饱溢,系統(tǒng)必須保證該事務(wù)對數(shù)據(jù)庫的改變不被丟失喧伞,即使數(shù)據(jù)庫出現(xiàn)故障。

3绩郎、啟動(dòng)事務(wù):使用 API 函數(shù)和 Transact-SQL 語句潘鲫,可以按顯式、自動(dòng)提交或隱式的方式來啟動(dòng)事務(wù)肋杖。

4溉仑、結(jié)束事務(wù):您可以使用 COMMIT(成功) 或 ROLLBACK(失敗) 語句状植,或者通過 API 函數(shù)來結(jié)束事務(wù)浊竟。

5、創(chuàng)建事務(wù)的原則

盡可能使事務(wù)保持簡短很重要津畸,當(dāng)事務(wù)啟動(dòng)后振定,數(shù)據(jù)庫管理系統(tǒng) (DBMS) 必須在事務(wù)結(jié)束之前保留很多資源、以保證事務(wù)的正確安全執(zhí)行肉拓。

特別是在大量并發(fā)的系統(tǒng)中后频, 保持事務(wù)簡短以減少并發(fā) 資源鎖定爭奪,將顯得更為重要暖途。

a卑惜、事務(wù)處理,禁止與用戶交互丧肴,在事務(wù)開始前完成用戶輸入残揉。

b、在瀏覽數(shù)據(jù)時(shí)芋浮,盡量不要打開事務(wù)

c抱环、盡可能使事務(wù)保持簡短。

d纸巷、考慮為只讀查詢使用快照隔離镇草,以減少阻塞。

e瘤旨、靈活地使用更低的事務(wù)隔離級別梯啤。

f、靈活地使用更低的游標(biāo)并發(fā)選項(xiàng)存哲,例如開放式并發(fā)選項(xiàng)因宇。

g七婴、在事務(wù)中盡量使訪問的數(shù)據(jù)量最小。


二察滑、事務(wù)的隔離級別

1打厘、事務(wù)常見的四種隔離級別

盡管數(shù)據(jù)庫為用戶提供了鎖的DML操作方式,但直接使用鎖管理是非常麻煩的贺辰,因此數(shù)據(jù)庫為用戶提供了自動(dòng)鎖機(jī)制户盯。只要用戶指定會(huì)話的事務(wù)隔離級別,數(shù)據(jù)庫就會(huì)分析事務(wù)中的SQL語句饲化,然后自動(dòng)為事務(wù)操作的數(shù)據(jù)資源添加上適合的鎖莽鸭。此外數(shù)據(jù)庫還會(huì)維護(hù)這些鎖,當(dāng)一個(gè)資源上的鎖數(shù)目太多時(shí)吃靠,自動(dòng)進(jìn)行鎖升級以提高系統(tǒng)的運(yùn)行性能硫眨,而這一過程對用戶來說完全是透明的。

ANSI/ISO SQL 92標(biāo)準(zhǔn)定義了4個(gè)等級的事務(wù)隔離級別撩笆,在相同數(shù)據(jù)環(huán)境下捺球,使用相同的輸入,執(zhí)行相同的工作夕冲,根據(jù)不同的隔離級別氮兵,可以導(dǎo)致不同的結(jié)果。不同事務(wù)隔離級別能夠解決的數(shù)據(jù)并發(fā)問題的能力是不同的歹鱼,如下表:


事務(wù)的隔離級別和數(shù)據(jù)庫并發(fā)性是對立的泣栈,兩者此增彼長。一般來說弥姻,使用READ UNCOMMITED隔離級別的數(shù)據(jù)庫擁有最高的并發(fā)性和吞吐量南片,而使用SERIALIZABLE隔離級別的數(shù)據(jù)庫并發(fā)性最低。

SQL 92定義READ UNCOMMITED主要是為了提供非阻塞讀的能力庭敦,Oracle雖然也支持READ UNCOMMITED疼进,但它不支持臟讀,因?yàn)镺racle使用多版本機(jī)制徹底解決了在非阻塞讀時(shí)讀到臟數(shù)據(jù)的問題并保證讀的一致性秧廉,所以伞广,Oracle的READ COMMITTED隔離級別就已經(jīng)滿足了SQL 92標(biāo)準(zhǔn)的REPEATABLE READ隔離級別。?SQL 92推薦使用REPEATABLE READ以保證數(shù)據(jù)的讀一致性疼电,不過用戶可以根據(jù)應(yīng)用的需要選擇適合的隔離等級嚼锄。

問題分析:

a、更新丟失:兩個(gè)事務(wù)都同時(shí)更新一行數(shù)據(jù)蔽豺,一個(gè)事務(wù)對數(shù)據(jù)的更新把另一個(gè)事務(wù)對數(shù)據(jù)的更新覆蓋了区丑。這是因?yàn)橄到y(tǒng)沒有執(zhí)行任何的鎖操作,并發(fā)事務(wù)沒有被隔離開來。

第一類更新丟失:A事務(wù)撤銷時(shí)沧侥,把已經(jīng)提交的B事務(wù)的更新數(shù)據(jù)覆蓋了可霎。這種錯(cuò)誤可能造成很嚴(yán)重的問題,通常數(shù)據(jù)庫的實(shí)現(xiàn)是不允許發(fā)生這種情況正什。


第二類更新丟失:A事務(wù)覆蓋B事務(wù)已經(jīng)提交的數(shù)據(jù)啥纸,造成B事務(wù)所做操作丟失。


b婴氮、臟讀(Dirty Read):一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)未提交的數(shù)據(jù)操作結(jié)果。這是相當(dāng)危險(xiǎn)的盾致,因?yàn)楹芸赡芩械牟僮鞫急换貪L主经。

c、不可重復(fù)讀(虛讀)(NonRepeatable Read):一個(gè)事務(wù)對同一行數(shù)據(jù)重復(fù)讀取兩次庭惜,但是卻得到了不同的結(jié)果罩驻。例如事務(wù)T1讀取某一數(shù)據(jù)后,事務(wù)T2對其做了修改护赊,當(dāng)事務(wù)T1再次讀該數(shù)據(jù)時(shí)得到與前一次不同的值惠遏。

d、幻讀(Phantom Read):事務(wù)在操作過程中進(jìn)行兩次查詢骏啰,第二次查詢的結(jié)果包含了第一次查詢中未出現(xiàn)的數(shù)據(jù)或者缺少了第一次查詢中出現(xiàn)的數(shù)據(jù)节吮,這是因?yàn)樵趦纱尾樵冞^程中有另外一個(gè)事務(wù)插入數(shù)據(jù)造成的。

隔離級別分析:

a判耕、讀未提交(Read Uncommitted):允許臟讀取透绩,但不允許更新丟失。這種事務(wù)隔離控制可以通過“排他寫鎖”實(shí)現(xiàn)壁熄。

b帚豪、讀提交(Read Committed):允許不可重復(fù)讀取,但不允許臟讀取草丧。這種事務(wù)隔離控制可以通過“瞬間共享讀鎖”和“排他寫鎖”實(shí)現(xiàn)狸臣。

c、可重復(fù)讀(Repeatable Read):禁止不可重復(fù)讀取和臟讀取昌执,但是有時(shí)可能出現(xiàn)幻影數(shù)據(jù)烛亦。這種事務(wù)隔離控制可以通過“共享讀鎖”和“排他寫鎖”實(shí)現(xiàn)。

d仙蚜、可序列化(Serializable):提供嚴(yán)格的事務(wù)隔離此洲。它要求事務(wù)序列化執(zhí)行,事務(wù)只能一個(gè)接著一個(gè)地執(zhí)行委粉,但不能并發(fā)執(zhí)行呜师。如果僅僅通過“行級鎖”是無法實(shí)現(xiàn)事務(wù)序列化的,必須通過其他機(jī)制保證新插入的數(shù)據(jù)不會(huì)被剛執(zhí)行查詢操作的事務(wù)訪問到贾节。

2汁汗、數(shù)據(jù)庫中衷畦,通常默認(rèn)隔離級別是“讀已提交”,在默認(rèn)的事務(wù)隔離級別下:insert知牌,update祈争,delete用的是排他鎖, 會(huì)等待事務(wù)完成。通常情況下可以把隔離級別設(shè)為Read Committed角寸,它能避免臟讀菩混,而且有較好的并發(fā)性能。盡管它會(huì)導(dǎo)致虛讀扁藕、幻讀等問題沮峡,在可能出現(xiàn)這類問題的個(gè)別場合可以由應(yīng)用程序釆用悲觀鎖或樂觀鎖來控制。

3亿柑、SQL語句執(zhí)行之前邢疙,一般可以通過自定義設(shè)置事務(wù)隔離級別,JDBC一般也支持修改會(huì)話級的事務(wù)隔離級別設(shè)置望薄。

4疟游、另外要提一點(diǎn):SQL標(biāo)準(zhǔn)對事務(wù)隔離級別的規(guī)定,是按該級別不可能發(fā)生什么問題來確定的痕支;所以颁虐,不同的數(shù)據(jù)庫對事務(wù)隔離的級別實(shí)現(xiàn)方式不一樣,比如采转,鎖的類型聪廉、鎖的作用范圍與鎖的有效時(shí)間。

5故慈、事務(wù)隔離級別的實(shí)現(xiàn)依據(jù)

a板熊、是否申請鎖和鎖類型

b、占用鎖的時(shí)間

c察绷、鎖的粒度

例如:共享鎖的鎖定時(shí)間與事務(wù)的隔離級別有關(guān)干签,如果隔離級別為Read

Committed的默認(rèn)級別,只在讀取(select)的期間保持鎖定拆撼,即在查詢出數(shù)據(jù)以后就釋放了鎖容劳;如果隔離級別為更高的Serializable直到事務(wù)結(jié)束才釋放鎖。另說明闸度,如果select語句中指定了HoldLock提示竭贩,則也要等到事務(wù)結(jié)束才釋放鎖。

三莺禁、鎖

1留量、事務(wù)使用鎖,防止其他用戶訪問一個(gè)還未完成的事務(wù)中的數(shù)據(jù)。對于多用戶系統(tǒng)來說楼熄,鎖機(jī)制是必須的忆绰。有多種類型的鎖,允許事務(wù)鎖定不同的資源可岂。鎖就是保護(hù)指定的資源错敢,不被其他事務(wù)操作。鎖定比較小的對象缕粹,例如鎖定行稚茅,雖然可以提高并發(fā)性,但是卻有較高的開支致开,因?yàn)槿绻i定許多行峰锁,那么需要占有更多的鎖。鎖定比較大的對象双戳,例如鎖定表,會(huì)大大降低并發(fā)性糜芳,因?yàn)殒i定整個(gè)表就限制了其他事務(wù)訪問該表的其他部分飒货,但是成本開支比較低,因?yàn)橹恍杈S護(hù)比較少的鎖峭竣。

2塘辅、鎖的特點(diǎn):

a、鎖是保證并發(fā)控制的手段

b皆撩、鎖的類型扣墩,主要包括共享鎖和排它鎖;共享鎖允許其他事務(wù)繼續(xù)使用鎖定的資源扛吞,排它鎖只允許一個(gè)事務(wù)訪問數(shù)據(jù)

c呻惕、鎖的粒度,可以鎖定的資源包括行滥比、頁亚脆、簇、表和數(shù)據(jù)庫

d盲泛、鎖的時(shí)間濒持,鎖的時(shí)間應(yīng)該包括兩種:一種是sql執(zhí)行完就釋放鎖,另一種是事務(wù)結(jié)束后釋放鎖寺滚。

3柑营、數(shù)據(jù)庫鎖機(jī)制

數(shù)據(jù)庫通過鎖的機(jī)制解決并發(fā)訪問的問題,雖然不同的數(shù)據(jù)庫在實(shí)現(xiàn)細(xì)節(jié)上存在差別村视,但原理基本上是一樣的官套。

按鎖定的對象的不同,一般可以分為表鎖定行鎖定,前者對整個(gè)表進(jìn)行鎖定虏杰,而后者對表中特定行進(jìn)行鎖定讥蟆。從并發(fā)事務(wù)鎖定的關(guān)系上看,可以分為共享鎖定獨(dú)占鎖定纺阔。共享鎖定會(huì)防止獨(dú)占鎖定瘸彤,但允許其他的共享鎖定。而獨(dú)占鎖定既防止其他的獨(dú)占鎖定笛钝,也防止其他的共享鎖定质况。

為了更改數(shù)據(jù),數(shù)據(jù)庫必須在進(jìn)行更改的行上施加行獨(dú)占鎖定玻靡,INSERT结榄、UPDATE、DELETE和SELECT FOR UPDATE語句都會(huì)隱式采用必要的行鎖定囤捻。

4臼朗、InnoDB引擎的鎖機(jī)制

共享鎖(S):允許一個(gè)事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖蝎土。

排他鎖(X):允許獲得排他鎖的事務(wù)更新數(shù)據(jù)视哑,阻止其他事務(wù)取得相同數(shù)據(jù)集的共享讀鎖和排他寫鎖。

意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖誊涯,事務(wù)在給一個(gè)數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖挡毅。

意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖暴构。

說明:

1)共享鎖和排他鎖都是行鎖跪呈,意向鎖都是表鎖,應(yīng)用中我們只會(huì)使用到共享鎖和排他鎖取逾,意向鎖是mysql內(nèi)部使用的耗绿,不需要用戶干預(yù)。

2)對于UPDATE菌赖、DELETE和INSERT語句缭乘,InnoDB會(huì)自動(dòng)給涉及數(shù)據(jù)集加排他鎖;對于普通SELECT語句琉用,InnoDB不會(huì)加任何鎖堕绩,事務(wù)可以通過以下語句顯示給記錄集加共享鎖或排他鎖。

共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE

3)InnoDB行鎖是通過給索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的邑时,因此InnoDB這種行鎖實(shí)現(xiàn)特點(diǎn)意味著:只有通過索引條件檢索數(shù)據(jù)奴紧,InnoDB才使用行級鎖,否則晶丘,InnoDB將使用表鎖黍氮!

5唐含、程序使用鎖(并發(fā)控制類型分為兩大類:樂觀并發(fā)控制和悲觀并發(fā)控制)

悲觀鎖( Pessimistic Locking )

悲觀鎖,正如其名沫浆,它指的是對數(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ù)過程中的鎖)躬审,外界無法修改這些記錄棘街。

Hibernate 的悲觀鎖,也是基于數(shù)據(jù)庫的鎖機(jī)制實(shí)現(xiàn)承边。

下面的代碼實(shí)現(xiàn)了對查詢記錄的加鎖:

String hqlStr ="from TUser as user where user.name='Erica'";

Query query = session.createQuery(hqlStr);

query.setLockMode("user", LockMode.UPGRADE); // 加鎖

List userList = query.list();// 執(zhí)行查詢蹬碧,獲取數(shù)據(jù)

query.setLockMode 對查詢語句中,特定別名所對應(yīng)的記錄進(jìn)行加鎖(我們?yōu)門User 類指定了一個(gè)別名 “user” )炒刁,這里也就是對返回的所有 user 記錄進(jìn)行加鎖。

Hibernate 通過使用數(shù)據(jù)庫的 for update 子句實(shí)現(xiàn)了悲觀鎖機(jī)制誊稚。

Hibernate 的加鎖模式有:

LockMode.NONE :無鎖機(jī)制翔始。

LockMode.WRITE :Hibernate 在 Insert 和 Update 記錄的時(shí)候會(huì)自動(dòng)獲取。

LockMode.READ :Hibernate 在讀取記錄的時(shí)候會(huì)自動(dòng)獲取里伯。

以上這三種鎖機(jī)制一般由 Hibernate 內(nèi)部使用城瞎,如 Hibernate 為了保證 Update過程中對象不會(huì)被外界修改,會(huì)在 save 方法實(shí)現(xiàn)中自動(dòng)為目標(biāo)對象加上 WRITE 鎖疾瓮。

LockMode.UPGRADE :利用數(shù)據(jù)庫的 for update 子句加鎖脖镀。

LockMode. UPGRADE_NOWAIT :Oracle 的特定實(shí)現(xiàn),利用 Oracle 的 for update nowait 子句實(shí)現(xiàn)加鎖狼电。

上面這兩種鎖機(jī)制是我們在應(yīng)用層較為常用的蜒灰,加鎖一般通過以下方法實(shí)現(xiàn):

Criteria.setLockMode

Query.setLockMode

Session.lock

注意,只有在查詢開始之前(也就是 Hiberate 生成 SQL 之前)設(shè)定加鎖肩碟,才會(huì)真正通過數(shù)據(jù)庫的鎖機(jī)制進(jìn)行加鎖處理强窖,否則,數(shù)據(jù)已經(jīng)通過不包含 for update 子句的 Select SQL 加載進(jìn)來削祈,所謂數(shù)據(jù)庫加鎖也就無從談起翅溺。

樂觀鎖( Optimistic Locking )

相對悲觀鎖而言脑漫,樂觀鎖機(jī)制采取了更加寬松的加鎖機(jī)制。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機(jī)制實(shí)現(xiàn)咙崎,以保證操作最大程度的獨(dú)占性优幸。但隨之而來的就是數(shù)據(jù)庫性能的大量開銷,特別是對長事務(wù)而言褪猛,這樣的開銷往往無法承受网杆。

如一個(gè)金融系統(tǒng),當(dāng)某個(gè)操作員讀取用戶的數(shù)據(jù)握爷,并在讀出的用戶數(shù)據(jù)的基礎(chǔ)上進(jìn)行修改時(shí)如更改用戶帳戶余額跛璧,如果采用悲觀鎖機(jī)制,也就意味著整個(gè)操作過程中(從操作員讀出數(shù)新啼、開始修改直至提交修改結(jié)果的全過程追城,甚至還包括操作員中途去煮咖啡的時(shí)間),數(shù)據(jù)庫記錄始終處于加鎖狀態(tài)燥撞,可以想見座柱,如果面對幾百上千個(gè)并發(fā),這樣的情況將導(dǎo)致怎樣的后果物舒。樂觀鎖機(jī)制在一定程度上解決了這個(gè)問題色洞。

樂觀鎖,大多是基于數(shù)據(jù)版本( Version

)記錄機(jī)制實(shí)現(xiàn)冠胯。何謂數(shù)據(jù)版本火诸?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識,在基于數(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ù)灼卢。

對于上面修改用戶帳戶信息的例子而言,假設(shè)數(shù)據(jù)庫中帳戶信息表中有一個(gè)version 字段堰怨,當(dāng)前值為 1 芥玉;而當(dāng)前帳戶余額字段(balance)為 $100 。

a> 操作員 A 此時(shí)將其讀出(version=1)备图,并從其帳戶余額中扣除 $50($100-$50)灿巧。

b> 在操作員 A 操作的過程中赶袄,操作員 B 也讀入此用戶信息(version=1)躬络,并從其帳戶余額中扣除 $20 ($100-$20)层亿。

c> 操作員 A 完成了修改工作,將數(shù)據(jù)版本號加一(version=2)卷中,連同帳戶扣除后余額(balance=$50)盾似,提交至數(shù)據(jù)庫更新敬辣,此時(shí)由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫記錄當(dāng)前版本,數(shù)據(jù)被更新零院,數(shù)據(jù)庫記錄 version 更新為 2 溉跃。

d> 操作員 B 完成了操作,也將版本號加一(version=2)試圖向數(shù)據(jù)庫提交數(shù)據(jù)(balance=$80)告抄,但此時(shí)比對數(shù)據(jù)庫記錄版本時(shí)發(fā)現(xiàn)撰茎,操作員 B 提交的數(shù)據(jù)版本號為 2 ,數(shù)據(jù)庫記錄當(dāng)前版本也為 2 打洼,不滿足“ 提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新“ 的樂觀鎖策略龄糊,因此,操作員 B 的提交被駁回募疮。這樣炫惩,就避免了操作員 B 用基于 version=1 的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員 A 的操作結(jié)果的可能。

從上面的例子可以看出阿浓,樂觀鎖機(jī)制避免了長事務(wù)中的數(shù)據(jù)庫加鎖開銷(操作員 A 和操作員 B 操作過程中他嚷,都沒有對數(shù)據(jù)庫數(shù)據(jù)加鎖),大大提升了大并發(fā)量下的系統(tǒng)整體性能表現(xiàn)芭毙。需要注意的是爸舒,樂觀鎖機(jī)制往往基于系統(tǒng)中的數(shù)據(jù)存儲(chǔ)邏輯,因此也具備一定的局限性稿蹲,如在上例中,由于樂觀鎖機(jī)制是在我們的系統(tǒng)中實(shí)現(xiàn)鹊奖,來自外部系統(tǒng)的用戶余額更新操作不受我們系統(tǒng)的控制苛聘,因此可能會(huì)造成臟數(shù)據(jù)被更新到數(shù)據(jù)庫中。在系統(tǒng)設(shè)計(jì)階段忠聚,我們應(yīng)該充分考慮到這些情況出現(xiàn)的可能性设哗,并進(jìn)行相應(yīng)調(diào)整(比如可以將樂觀鎖策略放在數(shù)據(jù)庫存儲(chǔ)過程中實(shí)現(xiàn),對外只開放基于此存儲(chǔ)過程的數(shù)據(jù)更新途徑两蟀,而不是將數(shù)據(jù)庫表直接對外公開)网梢。

Hibernate 在其數(shù)據(jù)訪問引擎中內(nèi)置了樂觀鎖實(shí)現(xiàn)。如果不用考慮外部系統(tǒng)對數(shù)據(jù)庫的更新操作赂毯,利用 Hibernate 提供的透明化樂觀鎖實(shí)現(xiàn)战虏,將大大提升我們的生產(chǎn)力拣宰。

Hibernate 中可以通過 class 描述符的 optimistic-lock 屬性結(jié)合 version描述符指定。

現(xiàn)在烦感,我們?yōu)橹笆纠械?TUser 加上樂觀鎖機(jī)制巡社。

1 . 首先為 TUser 的 class 描述符添加 optimistic-lock 屬性:

dynamic-insert="true" optimistic-lock="version">

……

optimistic-lock 屬性有如下可選取值:

none:無樂觀鎖

version:通過版本機(jī)制實(shí)現(xiàn)樂觀鎖

dirty:通過檢查發(fā)生變動(dòng)過的屬性實(shí)現(xiàn)樂觀鎖

all:通過檢查所有屬性實(shí)現(xiàn)樂觀鎖

其中通過 version 實(shí)現(xiàn)的樂觀鎖機(jī)制是 Hibernate 官方推薦的樂觀鎖實(shí)現(xiàn),同時(shí)也是 Hibernate 中手趣,目前唯一在數(shù)據(jù)對象脫離 Session 發(fā)生修改的情況下依然有效的鎖機(jī)制晌该。因此,一般情況下绿渣,我們都選擇 version 方式作為 Hibernate 樂觀鎖實(shí)現(xiàn)機(jī)制朝群。

2 . 添加一個(gè) Version 屬性描述符

optimistic-lock="version">

……

注意 version 節(jié)點(diǎn)必須出現(xiàn)在 ID 節(jié)點(diǎn)之后。這里我們聲明了一個(gè) version 屬性中符,用于存放用戶的版本信息姜胖,保存在 TUser 表的version 字段中。

在代碼中執(zhí) tx.commit() 時(shí)可能拋出 StaleObjectStateException 異常舟茶,指出版本檢查失敗谭期,說明當(dāng)前事務(wù)正在試圖提交一個(gè)過期數(shù)據(jù)。通過捕捉這個(gè)異常吧凉,我們就可以在樂觀鎖校驗(yàn)失敗時(shí)進(jìn)行相應(yīng)處理隧出。

五、Java中的三種事務(wù)

差異:

1阀捅、JDBC事務(wù)控制的局限性在一個(gè)數(shù)據(jù)庫連接內(nèi)胀瞪,但是其使用簡單。

2饲鄙、JTA事務(wù)的功能強(qiáng)大凄诞,事務(wù)可以跨越多個(gè)數(shù)據(jù)庫或多個(gè)DAO,使用也比較復(fù)雜忍级;應(yīng)用程序調(diào)用UserTransaction.begin()帆谍、 UserTransaction.commit() 和 serTransaction.rollback() 處理事務(wù)邊界。

3轴咱、容器事務(wù)汛蝙,主要指的是J2EE應(yīng)用服務(wù)器提供的事務(wù)管理,局限于EJB應(yīng)用使用朴肺。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窖剑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子戈稿,更是在濱河造成了極大的恐慌西土,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鞍盗,死亡現(xiàn)場離奇詭異需了,居然都是意外死亡跳昼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門援所,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庐舟,“玉大人,你說我怎么就攤上這事住拭∨猜裕” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵滔岳,是天一觀的道長杠娱。 經(jīng)常有香客問我,道長谱煤,這世上最難降的妖魔是什么摊求? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮刘离,結(jié)果婚禮上室叉,老公的妹妹穿的比我還像新娘。我一直安慰自己硫惕,他們只是感情好茧痕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恼除,像睡著了一般踪旷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豁辉,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天令野,我揣著相機(jī)與錄音,去河邊找鬼徽级。 笑死气破,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的餐抢。 我是一名探鬼主播堵幽,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弹澎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起努咐,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤苦蒿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后渗稍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佩迟,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡团滥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了报强。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灸姊。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秉溉,靈堂內(nèi)的尸體忽然破棺而出力惯,到底是詐尸還是另有隱情,我是刑警寧澤召嘶,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布父晶,位于F島的核電站,受9級特大地震影響弄跌,放射性物質(zhì)發(fā)生泄漏甲喝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一铛只、第九天 我趴在偏房一處隱蔽的房頂上張望埠胖。 院中可真熱鬧,春花似錦淳玩、人聲如沸直撤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谊惭。三九已至,卻和暖如春侮东,著一層夾襖步出監(jiān)牢的瞬間圈盔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工悄雅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驱敲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓宽闲,卻偏偏與公主長得像众眨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子容诬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容