【學習筆記】事務

1.事務概述

  • 什麼是事務

一件事情有n個組成單元,要麼這n個組成單元同時成功,要麼n個單元同時失敗。java

就是將n個組成單元放到一個事務中。mysql

  • mysql的事務

默認的事務:一條sql語句就是一個事務,默認開啓事務並提交面試

  • 手動事務:

1)顯式的開啓一個事務:start transactionsql

2)事務提交:commit表明從開啓事務到提交事務,中間全部的sql都認爲有效----真正的更新數據庫數據庫

3)事務的回滾:rollback 表明事務的回滾,從開啓事務到事務回滾,中間的全部的sql操做都認爲無效,數據庫沒有被更新安全

2.JDBC的事務操做

默認是自動事務:session

執行sql語句:executeUpdate()  ---- 每執行一次executeUpdate方法,表明事務自動提交併發

經過jdbc的API手動操做事務:oracle

(1)開啓事務:conn.setAutoCommit(false);工具

(2)提交事務:conn.commit();

(3)回滾事務:conn.rollback();

注意:控制事務的connnection必須是同一個(執行sql的connection與開啓事務的connnection必須是同一個才能對事務進行控制

3.DBUtils的事務操做

3.1 QueryRunner

有參構造方法:QueryRunner runner = new QueryRunner(DataSource dataSource);
有參構造方法將數據源(鏈接池)做爲參數傳入QueryRunner,QueryRunner會從鏈接池中得到一個數據庫鏈接資源connection來操做數據庫,因此直接使用無Connection參數的update方法便可操做數據庫。runner.update(String sql,.....)

無參構造方法:QueryRunner runner = new QueryRunner();
無參的構造方法沒有將數據源(鏈接池)做爲參數傳入QueryRunner,那麼咱們在使用QueryRunner對象操做數據庫時,要使用有Connection參數的方法。runner.update(Connection conn,String sql,......)

4.使用ThreadLocal綁定鏈接資源

a方法裏調用b方法,b方法又調用c方法,整個過程當中,都屬於一個線程,ThreadLocal是這個線程裏的公共區域,由於控制事務須要同一個connection,所以ThreadLocal裏存放connection來控制事務。ThreadLocal是一個Map類型的鍵值對

案例:轉帳

 

//封裝在工具類裏
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//......
// 獲取鏈接對象
	public static Connection getConnection() throws SQLException {
		Connection con = tl.get();//得到當前線程
		if (con == null) {//若是沒有connection,就從鏈接池得到get一個,並set放入當前線程
			con = dataSource.getConnection();
			tl.set(con);
		}
		return con;
	}
// 開啓事務
	public static void startTransaction() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.setAutoCommit(false);
		}
	}

	// 事務回滾
	public static void rollback() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.rollback();
		}
	}

	// 提交而且 關閉資源及從ThreadLocall中釋放
	public static void commitAndRelease() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.commit(); // 事務提交
			con.close();// 關閉資源
			tl.remove();// 從線程綁定中移除
		}
	}
public class TransferService {

	public boolean transferMoney(String out, String in, double money) {
		boolean b=true;
		TransferDao dao=new TransferDao();
		try {
			MyDataSourceUtils.startTransaction();
			dao.out(out,money);
//			int i=1/0;
			dao.in(in,money);
		} catch (Exception e) {
			b=false;
			try {
				MyDataSourceUtils.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			try {
				MyDataSourceUtils.commitAndRelease();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return b;
	}


}
public class TransferDao {

	public void out(String out, double money) throws SQLException {
		QueryRunner runner=new QueryRunner();
		String sql="update account set money=money-? where name=?";
		Connection conn = MyDataSourceUtils.getConnection();
		runner.update(conn, sql, money,out);
	}

	public void in(String in, double money) throws SQLException {
		QueryRunner runner=new QueryRunner();
		//updata找不到參數不會報錯,而是返回int,因此name錯誤依然顯示轉帳成功
		String sql="update account set money=money+? where name=?";
		Connection conn = MyDataSourceUtils.getConnection();
		runner.update(conn,sql, money,in);
		
	}

}

5.事務的特性和隔離級別(概念性問題---面試可能會有)

5.1事務的特性:ACID

1)原子性(Atomicity):原子性是指事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生。 

2)一致性(Consistency):一個事務中,事務先後數據的完整性必須保持一致。(數據未提交時查詢可能查詢結果不一樣)

3)隔離性(Isolation):多個事務,事務的隔離性是指多個用戶併發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個併發事務之間數據要相互隔離。

4)持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響。

5.2併發訪問問題----由隔離性引發

若是不考慮隔離性,事務存在三種併發訪問問題:

  1. 髒讀:B事務讀取到了A事務還沒有提交的數據   ------  要求B事務要讀取A事務提交的數據
  2. 不可重複讀:一個事務中,兩次讀取的數據的內容不一致  ----- 要求的是一個事務中屢次讀取時數據是一致的  --- update
  3. 幻讀/虛讀:一個事務中,兩次讀取的數據的數量不一致  ----- 要求在一個事務中屢次讀取的數據的數量是一致的 --insert  delet

5.3事務的隔離級別

  1. read uncommitted : 讀取還沒有提交的數據 :哪一個問題都不能解決
  2. read committed:讀取已經提交的數據 :能夠解決髒讀 ---- oracle默認的
  3. repeatable read:重讀讀取:能夠解決髒讀 和 不可重複讀 ---mysql默認的
  4. serializable:串行化:能夠解決 髒讀 不可重複讀 和 虛讀---至關於鎖表(多個訪問對數據庫的操做必須依次進行,(註冊)不多用)

注意:mysql數據庫默認的隔離級別
查看mysql數據庫默認的隔離級別:select @@tx_isolation
設置mysql的隔離級別:set session transaction isolation level 事務隔離級別(4種)

隔離級別的性能: read uncommitted>read committed>repeatable read>serialazable

安全性: read uncommitted<read committed<repeatable read<serialazable

相關文章
相關標籤/搜索