事務(wù)

一、事務(wù)概述

  1. 什么是事務(wù)
    一件事情有n個(gè)組成單元,要不這n個(gè)組成單元同時(shí)成功、要不n個(gè)單元就同時(shí)失敗;就是將n個(gè)組成單元放到一個(gè)事務(wù)中。

  2. mysql的事務(wù)
    默認(rèn)的事務(wù):一條sql語(yǔ)句就是一個(gè)事務(wù),默認(rèn)就開(kāi)啟事務(wù)并提交事務(wù)。
    手動(dòng)事務(wù):
    1)顯示的開(kāi)啟一個(gè)事務(wù):start transaction
    2)事務(wù)提交:commit 代表從開(kāi)啟事務(wù)到事務(wù)提交。中間所有的 sql 都認(rèn)為有效、真正的更新數(shù)據(jù)庫(kù)。
    3)事務(wù)的回滾:rollback 代表事務(wù)的回滾。從開(kāi)啟事務(wù)到事務(wù)回滾,中間的所有的 sql 操作都認(rèn)為無(wú)效、數(shù)據(jù)庫(kù)沒(méi)有被更新。

二、JDBC事務(wù)操作

默認(rèn)是自動(dòng)事務(wù):
執(zhí)行 sql 語(yǔ)句:executeUpdate() ----> 每執(zhí)行一次 executeUpdate 方法代表事務(wù)自動(dòng)提交

通過(guò) jdbc 的 API 手動(dòng)事務(wù):
開(kāi)啟事務(wù):conn.setAutoComnmit(false);
提交事務(wù):conn.commit();
回滾事務(wù):conn.rollback();
注意:控制事務(wù)的 connnection 必須是同一個(gè),即執(zhí)行 sql 的 connection 與開(kāi)啟事務(wù)的 connnection 必須是同一個(gè)才能對(duì)事務(wù)進(jìn)行控制。

public static void main(String[] args) {
      Connection conn = null;
      try {
           QueryRunner runner = new QueryRunner();
           //runner.update("update account set money=15000 where name='tom'");
           //獲得一個(gè)Connection
           conn = DataSourceUtils.getConnection();
           //開(kāi)啟事務(wù)
           conn.setAutoCommit(false);
           runner.update(conn, "update account set money=15000 where name='tom'");
           //提交或回滾事務(wù)
           conn.commit();
      } catch (SQLException e) {
           try {
               conn.rollback();
           } catch (SQLException e1) {
                e1.printStackTrace();
           }
           e.printStackTrace();
      }
}

三、DBUtils事務(wù)操作

  1. QueryRunner
    1)有參構(gòu)造:QueryRunner runner = new QueryRunner(DataSource dataSource);
    有參構(gòu)造將數(shù)據(jù)源(連接池)作為參數(shù)傳入QueryRunner,QueryRunner會(huì)從連接池中獲得一個(gè)數(shù)據(jù)庫(kù)連接資源操作數(shù)據(jù)庫(kù),所以直接使用無(wú) Connection 參數(shù)的 update 方法即可操作數(shù)據(jù)庫(kù)

    2)無(wú)參構(gòu)造:QueryRunner runner = new QueryRunner();
    無(wú)參的構(gòu)造沒(méi)有將數(shù)據(jù)源(連接池)作為參數(shù)傳入 QueryRunner ,那么我們?cè)谑褂?QueryRunner 對(duì)象操作數(shù)據(jù)庫(kù)時(shí)要使用有 Connection 參數(shù)的方法

四、使用ThreadLocal綁定連接資源

import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class MyDataSourceUtils {
     //獲得Connection ----- 從連接池中獲取
     private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
     //創(chuàng)建ThreadLocal
     private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
     //開(kāi)啟事務(wù)
     public static void startTransaction() throws SQLException{
          Connection conn = getCurrentConnection();
          conn.setAutoCommit(false);
     }

     //獲得當(dāng)前線程上綁定的conn
     public static Connection getCurrentConnection() throws SQLException{
          //從ThreadLocal尋找 當(dāng)前線程是否有對(duì)應(yīng)Connection
          Connection conn = tl.get();
          if(conn==null){
               //獲得新的connection
               conn = getConnection();
               //將conn資源綁定到ThreadLocal(map)上
               tl.set(conn);
          }
          return conn;
     }

     public static Connection getConnection() throws SQLException{
          return dataSource.getConnection();
     }

     //回滾事務(wù)
     public static void rollback() throws SQLException {
          getCurrentConnection().rollback();
     }

     //提交事務(wù)
     public static void commit() throws SQLException {
          Connection conn = getCurrentConnection();
          conn.commit();
          //將Connection從ThreadLocal中移除
          tl.remove();
          conn.close();     
     }
}

五、事務(wù)的特性和隔離級(jí)別(概念性問(wèn)題---面試)

  1. 事務(wù)的特性ACID
    1)原子性(Atomicity)原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
    2)一致性(Consistency)一個(gè)事務(wù)中,事務(wù)前后數(shù)據(jù)的完整性必須保持一致。
    3)隔離性(Isolation)多個(gè)事務(wù),事務(wù)的隔離性是指多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí), 一個(gè)用戶的事務(wù)不能被其它用戶的事務(wù)所干擾,多個(gè)并發(fā)事務(wù)之間數(shù)據(jù)要相互隔離。
    4)持久性(Durability)持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來(lái)即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。

  2. 并發(fā)訪問(wèn)問(wèn)題----由隔離性引起
    如果不考慮隔離性,事務(wù)存在3種并發(fā)訪問(wèn)問(wèn)題。
    1)臟讀:B事務(wù)讀取到了A事務(wù)尚未提交的數(shù)據(jù) ------ 要求B事務(wù)要讀取A事務(wù)提交的數(shù)據(jù)
    2)不可重復(fù)讀:一個(gè)事務(wù)中 兩次讀取的數(shù)據(jù)的內(nèi)容不一致 ----- 要求的是一個(gè)事務(wù)中多次讀取時(shí)數(shù)據(jù)是一致的 --- unpdate
    3)幻讀/虛讀:一個(gè)事務(wù)中 兩次讀取的數(shù)據(jù)的數(shù)量不一致 ----- 要求在一個(gè)事務(wù)多次讀取的數(shù)據(jù)的數(shù)量是一致的 --insert delete

  3. 事務(wù)的隔離級(jí)別
    1)read uncommitted : 讀取尚未提交的數(shù)據(jù) :哪個(gè)問(wèn)題都不能解決 ---- 1
    2)read committed:讀取已經(jīng)提交的數(shù)據(jù) :可以解決臟讀 ---- oracle默認(rèn)的 ---- 2
    3)repeatable read:重復(fù)讀取:可以解決臟讀 和 不可重復(fù)讀 --- mysql默認(rèn)的 ---- 4
    4)serializable:串行化:可以解決 臟讀 不可重復(fù)讀 和 虛讀--- 相當(dāng)于鎖表 ---- 8
    注意:mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別

查看mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別:select @@tx_isolation
設(shè)置mysql的隔離級(jí)別:set session transaction isolation level 設(shè)置事務(wù)隔離級(jí)別

查看mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
設(shè)置mysql的隔離級(jí)別
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容