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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Spring JDBC-Spring事务管理之数据库事务基础知识

發(fā)布時(shí)間:2025/3/21 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring JDBC-Spring事务管理之数据库事务基础知识 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  • 概述
  • 數(shù)據(jù)庫(kù)事務(wù)的概念
    • 原子性
    • 一致性
    • 隔離性
    • 持久性
  • 數(shù)據(jù)并發(fā)的問(wèn)題
    • 臟讀dirty read
    • 不可重復(fù)讀unrepeatable read
    • 幻象讀 phantom read
      • 幻象讀和不可重復(fù)度的區(qū)別
    • 第一類丟失更新
    • 第二類丟失更新
  • 數(shù)據(jù)庫(kù)鎖機(jī)制
  • 事務(wù)隔離級(jí)別
  • JDBC對(duì)事務(wù)的支持

概述

在使用Spring開(kāi)發(fā)應(yīng)用時(shí),Spring的事務(wù)管理可能是被使用最多、應(yīng)用最廣的功能。 Spring不但提供了和底層事務(wù)源無(wú)關(guān)的事務(wù)抽象,還提供了聲明性事務(wù)的功能,可以讓開(kāi)發(fā)者從事務(wù)代碼中解放出來(lái)


數(shù)據(jù)庫(kù)事務(wù)的概念

“一榮俱榮,一損俱損”。

數(shù)據(jù)庫(kù)事務(wù)必須同時(shí)滿足4個(gè)特性 (ACID):

  • 原子性Atomic

  • 一致性Consistency

  • 隔離性Isolation

  • 持久性Durability


原子性

表示組成一個(gè)事務(wù)的多個(gè)數(shù)據(jù)庫(kù)操作時(shí)一個(gè)不可分割的原子單元,只有所有的操作都成功,整個(gè)事務(wù)才提交。 事務(wù)中的任何一個(gè)數(shù)據(jù)庫(kù)操作失敗,已經(jīng)執(zhí)行的任何操作都必須回滾,讓數(shù)據(jù)庫(kù)返回到初始狀態(tài)。


一致性

事務(wù)操作成功后,數(shù)據(jù)庫(kù)所處的狀態(tài)和它的業(yè)務(wù)規(guī)則是一致的,即數(shù)據(jù)不會(huì)被破壞。 比如 A轉(zhuǎn)給B100元,不管操作成功與否,A賬戶和B賬戶的存款總額是不變的。


隔離性

在并發(fā)數(shù)據(jù)操作時(shí),不同的事務(wù)擁有各自的數(shù)據(jù)空間,他們的操作不會(huì)對(duì)對(duì)方產(chǎn)生干擾, 準(zhǔn)確的的說(shuō),并非要求做到完全無(wú)干擾,數(shù)據(jù)庫(kù)規(guī)定了多種事務(wù)隔離級(jí)別,不同的隔離級(jí)別對(duì)應(yīng)不同的干擾程度。 隔離級(jí)別越高,數(shù)據(jù)一致性越好,但并發(fā)性越弱。


持久性

一旦事務(wù)提供成功后,事務(wù)中所有的數(shù)據(jù)操作都必須被持久化到數(shù)據(jù)庫(kù)中。 即使在提交事務(wù)后,數(shù)據(jù)庫(kù)馬上崩潰,再重啟數(shù)據(jù)時(shí),也必須保證能通過(guò)某種機(jī)制恢復(fù)數(shù)據(jù)。


在這些事務(wù)特性中,數(shù)據(jù)的“一致性”是最終目標(biāo), 其他特性都是為了達(dá)到這個(gè)目標(biāo)而采取的措施、要求或者手段。

數(shù)據(jù)庫(kù)管理系統(tǒng)一般采取redolog來(lái)保證原子行、一致性和持久性。

數(shù)據(jù)庫(kù)管理系統(tǒng)采用數(shù)據(jù)庫(kù)鎖機(jī)制保證事物的隔離性,當(dāng)多個(gè)事務(wù)視圖對(duì)相同的數(shù)據(jù)機(jī)型操作時(shí),只有持有鎖的事務(wù)才能操作數(shù)據(jù),直到前面一個(gè)一個(gè)事務(wù)完成后,后面的事務(wù)才有機(jī)會(huì)對(duì)數(shù)據(jù)進(jìn)行操作。 Oracle還使用了數(shù)據(jù)版本你的機(jī)制,在回滾段為數(shù)據(jù)的每一個(gè)變化保存一個(gè)版本,數(shù)據(jù)的更改不影響數(shù)據(jù)的讀取。


數(shù)據(jù)并發(fā)的問(wèn)題

一個(gè)數(shù)據(jù)庫(kù)同時(shí)擁有多個(gè)訪問(wèn)客戶端,這些客戶端都可用并發(fā)的方式訪問(wèn)數(shù)據(jù)庫(kù)。 數(shù)據(jù)庫(kù)中相同的數(shù)據(jù)可能同時(shí)被多個(gè)事務(wù)訪問(wèn),如果沒(méi)有采取必要的隔離措施,就會(huì)導(dǎo)致各種并發(fā)問(wèn)題,破壞數(shù)據(jù)的完整性。

這些問(wèn)題可以歸結(jié)為5類,包括3類數(shù)據(jù)讀問(wèn)題(臟讀、不可重復(fù)度、幻象讀)和2類數(shù)據(jù)更新問(wèn)題(第一類丟失更新和第二類丟失更新)


臟讀dirty read

A 事務(wù)讀取了B事務(wù)尚未提交的更改數(shù)據(jù),并在這個(gè)數(shù)據(jù)的基礎(chǔ)上進(jìn)行操作。如果恰巧B事務(wù)回滾,那么A事務(wù)獨(dú)到的數(shù)據(jù)根本是不被承認(rèn)的。

時(shí)間轉(zhuǎn)賬事務(wù)A取款事務(wù)B
T1開(kāi)始事務(wù)
T2開(kāi)始事務(wù)
T3查詢賬戶為1000元
T4取出500,更改余額為500
T5查詢賬戶余額為500(臟讀)
T6撤銷事務(wù),余額恢復(fù)為1000
T7匯入100,余額更改為600
T8提交事務(wù)

在這個(gè)場(chǎng)景中,B希望取款500,而后又撤銷了動(dòng)作,而A相同的裝回轉(zhuǎn)入100,就因?yàn)锳事務(wù)讀取了B事務(wù)尚未提交的數(shù)據(jù),因而造成B賬戶白白丟失了500元。

在Oracle數(shù)據(jù)庫(kù)中,不會(huì)發(fā)生臟讀的情況。


不可重復(fù)讀unrepeatable read

不可重復(fù)讀是指A事務(wù)讀取了B事務(wù)已經(jīng)提交的更改數(shù)據(jù)。

時(shí)間取款事務(wù)A轉(zhuǎn)賬事務(wù)B
T1開(kāi)始事務(wù)
T2開(kāi)始事務(wù)
T3查詢賬戶為1000元
T4查詢賬戶為1000元
T5取出100,將余額更改為900
T6提交事務(wù)
T7查詢賬戶余額為900(和T4讀取的不一致)

幻象讀 phantom read

A事務(wù)讀取了B事務(wù)提交的新增數(shù)據(jù),這時(shí)A事務(wù)將出現(xiàn)幻象讀的問(wèn)題。 幻象讀一般發(fā)生在計(jì)算統(tǒng)計(jì)數(shù)據(jù)的事務(wù)中。

舉個(gè)例子:假設(shè)銀行系統(tǒng)在同一個(gè)事務(wù)中兩次統(tǒng)計(jì)存款賬戶的總金額,再?zèng)霾私y(tǒng)計(jì)過(guò)程中,剛好新增了一個(gè)存款賬戶,并存入100元。 這時(shí),兩次統(tǒng)計(jì)的金額將不一致。

時(shí)間統(tǒng)計(jì)金額事務(wù)A轉(zhuǎn)賬事務(wù)B
T1開(kāi)始事務(wù)
T2開(kāi)始事務(wù)
T3統(tǒng)計(jì)總存款數(shù)為1000元
T4新增一個(gè)存款賬戶,存入100
T5提交事務(wù)
T6再此統(tǒng)計(jì)存款總數(shù)為1100(幻象讀)

如果新增數(shù)據(jù)剛好滿足事務(wù)的查詢條件,那么這個(gè)新數(shù)據(jù)就進(jìn)入了事務(wù)的視野,因此產(chǎn)生了兩次統(tǒng)計(jì)結(jié)果不一致的情況。


幻象讀和不可重復(fù)度的區(qū)別

幻象讀是指讀到了其他已經(jīng)提交的新增數(shù)據(jù)

不可重復(fù)讀是指讀到了已經(jīng)提交事務(wù)的更改數(shù)據(jù)(更改或者刪除)

為了避免這兩種情況,采取的策略是不同的:

為了防止讀到更改數(shù)據(jù),只需要對(duì)操作的數(shù)據(jù)添加行級(jí)鎖,組織操作中的數(shù)據(jù)發(fā)生變化。

而為了防止讀到新增數(shù)據(jù),這往往需要添加表級(jí)鎖,將整張表鎖定,防止新增數(shù)據(jù),(Oracle使用多版本數(shù)據(jù)的方式實(shí)現(xiàn))


第一類丟失更新

A事務(wù)撤銷時(shí),把已經(jīng)提交的B事務(wù)的更新數(shù)據(jù)覆蓋了。

時(shí)間取款事務(wù)A轉(zhuǎn)賬事務(wù)B
T1開(kāi)始事務(wù)
T2開(kāi)始事務(wù)
T3查詢賬戶為1000元
T4查詢賬戶為1000元
T5匯入100,將余額更改為1100
T6提交事務(wù)
T7取出100,將余額更改為900
T8撤銷事務(wù)
T8余額恢復(fù)為1000(丟失更新)

A事務(wù)再撤銷時(shí),“不小心”將B事務(wù)已經(jīng)轉(zhuǎn)入賬戶的金額抹去了。


第二類丟失更新

A事務(wù)覆蓋B事務(wù)已經(jīng)提交的數(shù)據(jù),造成B事務(wù)所做操作丟失

時(shí)間轉(zhuǎn)賬事務(wù)A取款事務(wù)B
T1開(kāi)始事務(wù)
T2開(kāi)始事務(wù)
T3查詢賬戶為1000元
T4查詢賬戶為1000元
T5取出100,將余額更改為900
T6提交事務(wù)
T7匯入100
T8提交事務(wù)
T8余額恢復(fù)為1100(丟失更新)

由于支票轉(zhuǎn)賬事務(wù)覆蓋了取款事務(wù)對(duì)存款余額所做的更新,導(dǎo)致銀行損失了100, 相反,如果轉(zhuǎn)轉(zhuǎn)事務(wù)先提交,那么用戶將損失100元。


數(shù)據(jù)庫(kù)鎖機(jī)制

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

鎖的分類(oracle)

一、按操作劃分,可分為DML鎖、DDL鎖

二、按鎖的粒度劃分,可分為表級(jí)鎖、行級(jí)鎖、頁(yè)級(jí)鎖(mysql)

三、按鎖級(jí)別劃分,可分為共享鎖、排他鎖

四、按加鎖方式劃分,可分為自動(dòng)鎖、顯示鎖

五、按使用方式劃分,可分為樂(lè)觀鎖、悲觀鎖

為了更改數(shù)據(jù),數(shù)據(jù)庫(kù)必須在進(jìn)行更改的行上施加行獨(dú)占鎖定,insert、update、delete、select for update語(yǔ)句都會(huì)隱士采用必要的行鎖定。

下面介紹oracle常用的5中鎖定

  • 1、行共享鎖定:一般通過(guò)select for update 語(yǔ)句隱式獲得。行共享鎖定并不防止對(duì)數(shù)據(jù)行進(jìn)行更改的操作,但是可以防止其他會(huì)話獲取獨(dú)占性數(shù)據(jù)表鎖定。允許進(jìn)行多個(gè)并發(fā)的行共享和行獨(dú)占性鎖定,還允許進(jìn)行數(shù)據(jù)表的共享或者采用共享行獨(dú)占鎖定。

  • 2、行獨(dú)占鎖定:通過(guò)一條insert、update、delete語(yǔ)句隱士獲取,或者通過(guò)一條LOCK TABLE ROW EXCLUSIVE MODE語(yǔ)句顯示獲取。這個(gè)鎖可以防止其他會(huì)話獲取一個(gè)共享鎖定,共享行獨(dú)占鎖定或獨(dú)占鎖定。

  • 3、表共享鎖定:通過(guò)LOCK TABLE IN SHARE MODE語(yǔ)句顯示獲得,這種鎖定可以防止其他會(huì)話獲取行獨(dú)占鎖定(insert,update,delete),或者防止其他表共享行獨(dú)占鎖定或表獨(dú)占鎖定,它允許在表中擁有多個(gè)行共享和表共享鎖定,該鎖定可以讓會(huì)話具有對(duì)表事務(wù)級(jí)一致性訪問(wèn),因?yàn)槠渌麜?huì)話在用戶提交或者回溯該事務(wù)并釋放對(duì)該表的鎖定之前不能更改這個(gè)被鎖定的表。

  • 4、表共享行獨(dú)占鎖定:通過(guò) LOCK TABLE IN SHARE ROW EXCLUSIVE MODE語(yǔ)句顯示獲得。這種鎖定可以防止其他會(huì)話獲取一個(gè)表共享、行獨(dú)占或者表獨(dú)占鎖定,它允許其他行共享鎖定,它允許其他行共享鎖定。這種鎖定類似于表共享鎖定,只是一次只能對(duì)一個(gè)表放置一個(gè)表共享行獨(dú)占鎖定。如果A會(huì)話擁有該鎖定,則B會(huì)話可以執(zhí)行select for update操作,但如果B會(huì)話試圖更新選擇的行,則需要等待。

  • 5、表獨(dú)占:通過(guò)LOCK TABLE IN EXCLUSIVE MODE顯示獲得。這個(gè)鎖定防止其他會(huì)話對(duì)該表的任何鎖定。


事務(wù)隔離級(jí)別

因?yàn)橹苯邮褂脭?shù)據(jù)的鎖比較麻煩,用戶可以設(shè)置事務(wù)的隔離級(jí)別來(lái)實(shí)現(xiàn)自動(dòng)鎖機(jī)制。通過(guò)設(shè)置事務(wù)的隔離級(jí)別,數(shù)據(jù)庫(kù)就會(huì)分析事務(wù)中的SQL語(yǔ)句,然后自動(dòng)為事務(wù)操作的數(shù)據(jù)資源加上適合的鎖。

隔離級(jí)別臟讀不可重復(fù)度幻像讀第一類丟失更新第二類丟失更新
TRANSACTION_READ_UNCOMMITTED允許允許允許不允許允許
TRANSACTION_READ_COMMITTED不允許允許允許不允許允許
TRANSACTION_REPEATABLE_READ不允許不允許允許不允許不允許
TRANSACTION_SERIALIZABLE不允許不允許不允許不允許不允許

JDBC對(duì)事務(wù)的支持

并不是所有的數(shù)據(jù)庫(kù)都支持事務(wù),即使支持事務(wù)的數(shù)據(jù)庫(kù)也并非支持所有的事務(wù)隔離級(jí)別,用戶可以通過(guò)Connection的getMetaData()方法獲取DatabaseMetaData對(duì)象,并通過(guò)該對(duì)象的supportsTransactions()、supportsTransactionIsolationLevel(int level)方法查看底層數(shù)據(jù)庫(kù)的事務(wù)支持情況。

Connection默認(rèn)情況下是自動(dòng)提交的,也即每條執(zhí)行的SQL都對(duì)應(yīng)一個(gè)事務(wù),為了能夠?qū)⒍鄺lSQL當(dāng)成一個(gè)事務(wù)執(zhí)行,必須先通過(guò)Connection的setAutoCommit(false)阻止Connection自動(dòng)提交,并可通過(guò)Connection的setTransactionIsolation()設(shè)置事務(wù)的隔離級(jí)別,Connection中定義了對(duì)應(yīng)SQL 92標(biāo)準(zhǔn)4個(gè)事務(wù)隔離級(jí)別的常量。通過(guò)Connection的commit()提交事務(wù),通過(guò)Connection的rollback()回滾事務(wù)。

下面是典型的JDBC事務(wù)數(shù)據(jù)操作的代碼:

Connection conn ; try{ conn = DriverManager.getConnection();//①獲取數(shù)據(jù)連接 conn.setAutoCommit(false); //②關(guān)閉自動(dòng)提交的機(jī)制 //③設(shè)置事務(wù)隔離級(jí)別 conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); Statement stmt = conn.createStatement(); int rows = stmt.executeUpdate( "INSERT INTO t_topic ALUES(1,’tom’) " ); rows = stmt.executeUpdate( "UPDATE t_user set topic_nums = topic_nums +1 "+ "WHERE user_id = 1"); conn.commit();//④提交事務(wù) }catch(Exception e){ … conn.rollback();//⑤回滾事務(wù) }finally{ … }

在JDBC2.0中,事務(wù)只有兩個(gè)操作: 提交或者回滾。
在JDBC3.0(Java1.4以及以后的版本)引入了保存點(diǎn)特性。 JDBC定義了SavePoint接口,提供在一個(gè)更細(xì)粒度的事務(wù)控制機(jī)制。當(dāng)設(shè)置了一個(gè)保存點(diǎn)后,可以rollback到該保存點(diǎn)處的狀態(tài),而不是rollback整個(gè)事務(wù)。Connection接口的setSavepoint和releaseSavepoint方法可以設(shè)置和釋放保存點(diǎn)

Statement stmt = conn.createStatement(); int rows = stmt.executeUpdate( "INSERT INTO t_topic VALUES(1,’tom’)"); Savepoint svpt = conn.setSavepoint("savePoint1");//①設(shè)置一個(gè)保存點(diǎn) rows = stmt.executeUpdate( "UPDATE t_user set topic_nums = topic_nums +1 "+ "WHERE user_id = 1"); … //②回滾到①處的savePoint1,①之前的SQL操作,在整個(gè)事務(wù)提交后依然提交, //但①到②之間的SQL操作被撤銷了 conn.rollback(svpt); … conn.commit();//③提交事務(wù)

并非所有數(shù)據(jù)庫(kù)都支持保存點(diǎn)功能,用戶可以通過(guò)DatabaseMetaData的supportsSavepoints()方法查看是否支持。


總結(jié)

以上是生活随笔為你收集整理的Spring JDBC-Spring事务管理之数据库事务基础知识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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