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

數(shù)據(jù)庫(kù)事務(wù)介紹

事務(wù):一組邏輯操作單元,使數(shù)據(jù) 從一種狀態(tài)變換到另一種狀態(tài)。

  • 一組邏輯操作單元:一個(gè)或多個(gè)DML操作(增刪改)

事務(wù)處理原則:保證所有事務(wù)都作為一個(gè)工作單元來(lái)執(zhí)行,即使出現(xiàn)了故障聂受,都不能改變這種執(zhí)行方式扮饶。當(dāng)一個(gè)事務(wù)中執(zhí)行多個(gè)操作時(shí)逗鸣,要么所有的事務(wù)都被提交(commit)枝嘶,那么這些修改就永久地保存下來(lái)帘饶,要么數(shù)據(jù)庫(kù)管理系統(tǒng)將放棄所做的所有修改,整個(gè)事務(wù)回滾(rollback)到最初狀態(tài)群扶。

JDBC事務(wù)處理

數(shù)據(jù)一旦提交及刻,就不可回滾。

哪些操作會(huì)導(dǎo)致數(shù)據(jù)的自動(dòng)提交竞阐?

  • DDL操作一旦執(zhí)行缴饭,都會(huì)自動(dòng)提交。set autocomit = false對(duì)DDL操作無(wú)效馁菜。
  • DML操作默認(rèn)情況下茴扁,一旦執(zhí)行,就會(huì)自動(dòng)提交汪疮,我們可以通過(guò)set autocomit = false的方式取消DML操作的自動(dòng)提交峭火。
  • 默認(rèn)在關(guān)閉連接時(shí),會(huì)自動(dòng)地提交數(shù)據(jù)智嚷。

以上的三種情況卖丸,要都避免。

在編寫(xiě)代碼過(guò)程中盏道,可以取消自動(dòng)提交稍浆,以及控制何時(shí)關(guān)閉連接〔轮觯可以通過(guò)下面的三個(gè)方法讓一個(gè)或多個(gè)DML操作作為一個(gè)事務(wù)執(zhí)行:

setAutoCommit(false):Connection對(duì)象的方法衅枫,取消自動(dòng)提交事務(wù)。

commit():在所有的SQL語(yǔ)句都成功執(zhí)行后朗伶,調(diào)用該方法提交事務(wù)弦撩。

rollback():在出現(xiàn)異常時(shí),調(diào)用該方法回滾事務(wù)论皆。

若此時(shí)Connection沒(méi)有被關(guān)閉益楼,還可能被重復(fù)使用,尤其是在使用數(shù)據(jù)庫(kù)連接池技術(shù)時(shí)点晴,執(zhí)行close()方法前感凤,建議恢復(fù)自動(dòng)提交狀態(tài)setAutoCommit(true)。

案例

用戶(hù)AA向用戶(hù)BB轉(zhuǎn)賬100:

@Test
public void testUpdate() {

    Connection conn = null;
    try {
        // 1. 獲取數(shù)據(jù)庫(kù)連接粒督,在此獲取連接陪竿,保證之后的DML操作在同一個(gè)連接下進(jìn)行。
        conn = JDBCUtils.getConnection();
        // 2. 關(guān)閉自動(dòng)提交
        conn.setAutoCommit(false);
        // 3. 進(jìn)行數(shù)據(jù)庫(kù)操作
        String sql1 = "update user_table set balance = balance - 100 where user = ?";
        update(conn, sql1, "AA");

        // 模擬網(wǎng)絡(luò)異常
        System.out.println(10 / 0);

        String sql2 = "update user_table set balance = balance + 100 where user = ?";
        update(conn, sql2, "BB");
        // 若沒(méi)有異常屠橄,提交事務(wù)
        conn.commit();
        System.out.println("轉(zhuǎn)賬成功");
    } catch (Exception e) {
        e.printStackTrace();
        // 5. 若有異常萨惑,則回滾事務(wù)
        try {
            conn.rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    } finally {
        try {
            // 6. 恢復(fù)每次DML操作的自動(dòng)提交功能
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 7. 關(guān)閉連接
        JDBCUtils.closeResouse(conn, null);
    }
}

//通用的增刪改操作 ---- version 2.0 考慮事務(wù)
public int update(Connection conn, String sql, Object ...args) {

    PreparedStatement ps = null;
    try {
        // 1. 預(yù)編譯sql語(yǔ)句捐康,返回PreparedStatement的實(shí)例
        ps = conn.prepareStatement(sql);
        // 2. 填充占位符
        for (int i = 0; i < args.length; i++) {
            ps.setObject(i + 1, args[i]);
        }
        // 3. 執(zhí)行
        return ps.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 4. 關(guān)閉資源
        JDBCUtils.closeResouse(null, ps);
    }

    return 0;
}

事務(wù)的ACID屬性

  1. 原子性(Atomicity
    原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生庸蔼,要么都不發(fā)生。

  2. 一致性(Consistency
    事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變換到另外一個(gè)一致性狀態(tài)贮匕。

  3. 隔離性(Isolation
    事務(wù)的隔離性是指一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾姐仅,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾刻盐。

  4. 持久性(Durability
    持久性是指一個(gè)事務(wù)一旦被提交掏膏,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來(lái)的其他操作和數(shù)據(jù)庫(kù)故障不應(yīng)該對(duì)其有任何影響敦锌。

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

對(duì)于同時(shí)運(yùn)行的多個(gè)事務(wù), 當(dāng)這些事務(wù)訪問(wèn)數(shù)據(jù)庫(kù)中相同的數(shù)據(jù)時(shí), 如果沒(méi)有采取必要的隔離機(jī)制, 就會(huì)導(dǎo)致各種并發(fā)問(wèn)題:

  • 臟讀: 對(duì)于兩個(gè)事務(wù) T1, T2, T1 讀取了已經(jīng)被 T2 更新但還沒(méi)有被提交的字段馒疹。之后, 若 T2 回滾, T1讀取的內(nèi)容就是臨時(shí)且無(wú)效的。

  • 不可重復(fù)讀: 對(duì)于兩個(gè)事務(wù)T1, T2, T1 讀取了一個(gè)字段, 然后 T2 更新了該字段乙墙。之后, T1再次讀取同一個(gè)字段, 值就不同了颖变。

  • 幻讀: 對(duì)于兩個(gè)事務(wù)T1, T2, T1 從一個(gè)表中讀取了一個(gè)字段, 然后 T2 在該表中插入了一些新的行。之后, 如果 T1 再次讀取同一個(gè)表, 就會(huì)多出幾行听想。

數(shù)據(jù)庫(kù)事務(wù)的隔離性: 數(shù)據(jù)庫(kù)系統(tǒng)必須具有隔離并發(fā)運(yùn)行各個(gè)事務(wù)的能力, 使它們不會(huì)相互影響, 避免各種并發(fā)問(wèn)題腥刹。

一個(gè)事務(wù)與其他事務(wù)隔離的程度稱(chēng)為隔離級(jí)別。數(shù)據(jù)庫(kù)規(guī)定了多種事務(wù)隔離級(jí)別汉买,不同隔離級(jí)別對(duì)應(yīng)不同的干擾程度衔峰,隔離級(jí)別越高,數(shù)據(jù)一致性就越好, 但并發(fā)性越弱蛙粘。

四種隔離級(jí)別

數(shù)據(jù)庫(kù)提供的4種事務(wù)隔離級(jí)別:

隔離級(jí)別 描述
READ UNCOMMITTED(讀未提交) 允許事務(wù)讀取為被其他事務(wù)提交的變更垫卤,臟讀、不可重復(fù)讀和幻讀問(wèn)題仍然可能出現(xiàn)
READ COMMITTED(讀已提交) 只允許事務(wù)讀取已經(jīng)被其他事務(wù)提交的變更出牧,可以避免臟讀穴肘,但不可重復(fù)讀和幻讀問(wèn)題仍然可能出現(xiàn)
REPEATABLE READ(可重復(fù)讀) 確保事務(wù)可以多次從一個(gè)字段中讀取相同的值,在這個(gè)事務(wù)持續(xù)期間崔列,禁止其他事務(wù)對(duì)這個(gè)字段進(jìn)行更新梢褐,可以避免臟讀和不可重復(fù)讀,但幻讀的問(wèn)題仍然存在
SERIALIZABLE(串行化) 確保事務(wù)可以從一個(gè)表中讀取相同的行赵讯,在這個(gè)事務(wù)持續(xù)期間盈咳,禁止其他事務(wù)對(duì)該表執(zhí)行插入,更新和刪除操作边翼,所有并發(fā)問(wèn)題都可以避免鱼响,但性能十分低下

Oracle支持的 2 種事務(wù)隔離級(jí)別:READ COMMITED, SERIALIZABLE。 Oracle 默認(rèn)的事務(wù)隔離級(jí)別為: READ COMMITED 组底。

Mysql支持 4 種事務(wù)隔離級(jí)別丈积。Mysql 默認(rèn)的事務(wù)隔離級(jí)別為: REPEATABLE READ筐骇。

在MySQL中設(shè)置隔離界別

每啟動(dòng)一個(gè) mysql 程序,就會(huì)獲得一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)連接江滨。每個(gè)數(shù)據(jù)庫(kù)連接都有一個(gè)全局變量 @@tx_isolation铛纬,表示當(dāng)前的事務(wù)隔離級(jí)別。

  • 查看當(dāng)前的隔離級(jí)別:

    SELECT @@tx_isolation;
    
  • 設(shè)置當(dāng)前mysql連接的隔離級(jí)別:

    set transaction isolation level read committed;
    
  • 設(shè)置數(shù)據(jù)庫(kù)系統(tǒng)的全局的隔離級(jí)別:

    set global transaction isolation level read committed;
    

補(bǔ)充操作:

  • 創(chuàng)建mysql數(shù)據(jù)庫(kù)用戶(hù):

    create user tom identified by '123456';
    
  • 授予權(quán)限:

    # 授予通過(guò)網(wǎng)絡(luò)方式登錄的tom用戶(hù)對(duì)所有庫(kù)所有表的全部權(quán)限唬滑,密碼設(shè)為123456
    grant all privileges on *.* to tom@'%' identified by '123456';
    
    # 給tom用戶(hù)使用本地命令行方式告唆,授予test這個(gè)庫(kù)下的所有表的增刪改查的權(quán)限
    grant select,insert,delete,update on test.* to tom@localhost identified by 123456;
    

在Java代碼中想要獲取和修改數(shù)據(jù)庫(kù)當(dāng)前連接的隔離級(jí)別可以使用下面兩個(gè)方法:

getTransactionIsolation():使用Connection對(duì)象調(diào)用,獲取當(dāng)前連接的隔離級(jí)別晶密。

setTransactionIsolation():使用Connection對(duì)象調(diào)用擒悬,設(shè)置當(dāng)前連接的隔離級(jí)別。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末稻艰,一起剝皮案震驚了整個(gè)濱河市懂牧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尊勿,老刑警劉巖僧凤,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異运怖,居然都是意外死亡拼弃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)摇展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吻氧,“玉大人,你說(shuō)我怎么就攤上這事咏连《⑺铮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵祟滴,是天一觀的道長(zhǎng)振惰。 經(jīng)常有香客問(wèn)我茧痕,道長(zhǎng)吼拥,這世上最難降的妖魔是什么袄琳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任具壮,我火速辦了婚禮,結(jié)果婚禮上桌肴,老公的妹妹穿的比我還像新娘蛋辈。我一直安慰自己瑟慈,他們只是感情好漫谷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布仔雷。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碟婆。 梳的紋絲不亂的頭發(fā)上电抚,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音竖共,去河邊找鬼蝙叛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛公给,可吹牛的內(nèi)容都是我干的甥温。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼妓布,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了宋梧?” 一聲冷哼從身側(cè)響起匣沼,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捂龄,沒(méi)想到半個(gè)月后释涛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倦沧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年唇撬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片展融。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窖认,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出告希,到底是詐尸還是另有隱情扑浸,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布燕偶,位于F島的核電站喝噪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏指么。R本人自食惡果不足惜酝惧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伯诬。 院中可真熱鬧晚唇,春花似錦、人聲如沸姑廉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至萌踱,卻和暖如春葵礼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背并鸵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鸳粉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人园担。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓届谈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親弯汰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艰山,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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