MySQL事物提交與回滾

(一)什麼是事物?java

事務是邏輯上的一組操做,組成這組操做的各個單元,要不全都成功要不全都失敗,這個特性就是事務。事務是必須知足4個條件(ACID): Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)。mysql

(二)事物提交與回滾sql

在 MySQL 命令行的默認設置下,事務都是自動提交的,即執行 SQL 語句後就會立刻執行 COMMIT 操做。所以要顯式地開啓一個事務務須使用命令 BEGIN 或 START TRANSACTION,或者執行命令 SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。數據庫

例子:默認JDBC設置spa

public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			//conn.setAutoCommit(false);//設置自動事務提交爲false
			//a給b轉帳-----a帳戶減去100塊錢;b帳戶增長100塊錢
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			int i = 1 / 0;	//設置異常
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}

代碼解析:默認狀況下每執行一條sql語句,就是執行一次事務,也就是每一條sql語句的執行都會是一次事務的提交。在這個例子中若是a給b轉帳,a帳戶減去100的sql語句執行成功,這時伴隨着一次的事務提交,數據庫中的a帳戶金額減去100;而再執行b的帳務增長100sql語句以前,出現了異常,這裏我設了一個除以零異常,此時程序終止,bsql語句再也不執行。a帳戶扣了100,而b帳戶則金額不變。這時數據出錯。命令行

解決方法是:經過conn.setAutoCommit(false);方法設置事務自動提交爲false。這時每一次的sql語句執行完成後就不會提交事務,數據庫中的數據並不會發生改變,當倆個sql都執行完成,而後調用coon.commit();方法提交事務,此時數據庫中的數據纔會真正的改變。若是中途發生異常,經過conn.rollback();方法回滾,此時以前執行的sql語句的結果並不會提交。這樣數據就不會出錯了。code

知識點:當一個鏈接對象被建立時,默認狀況下JDBC是自動提交事務:每次執行一個 SQL 語句時,若是執行成功,就會向數據庫自動提交,而不能回滾。如想多條SQL在同一事務中,可以使用下列語句:
☆JDBC控制事務語句
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();對象

例子:設置setAutoCommit(false),和事物回滾點事務

public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		Savepoint point = null;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);//設置自動事務提交爲false
			
			//a給b轉帳-----a帳戶減去100塊錢;b帳戶增長100塊錢
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			point = conn.setSavepoint();
			int i = 1 / 0;
			
			//a給b轉帳-----a帳戶減去100塊錢;b帳戶增長100塊錢
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				if(point == null) {
					conn.rollback();
				} else {
					conn.rollback(point);
					conn.commit();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}

知識點:ci

☆設置事務回滾點

Savepoint sp = conn.setSavepoint();
Conn.rollback(sp);  //回滾
Conn.commit();   //回滾後必需要提交

(三)在MYSQL 事務處理主要有兩種方法:

一、用 BEGIN, ROLLBACK, COMMIT來實現

  • BEGIN 開始一個事務
  • ROLLBACK 事務回滾
  • COMMIT 事務確認

二、直接用 SET 來改變 MySQL 的自動提交模式:

  • SET AUTOCOMMIT=0 禁止自動提交
  • SET AUTOCOMMIT=1 開啓自動提交

例子: 

mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb;  # 建立數據表
Query OK, 0 rows affected (0.04 sec)
 
mysql> select * from runoob_transaction_test;
Empty set (0.01 sec)
 
mysql> begin;  # 開始事務
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
 
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
 
mysql> commit; # 提交事務
Query OK, 0 rows affected (0.01 sec)
 
mysql>  select * from runoob_transaction_test;
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
 
mysql> begin;    # 開始事務
Query OK, 0 rows affected (0.00 sec)
 
mysql>  insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
 
mysql> rollback;   # 回滾
Query OK, 0 rows affected (0.00 sec)
 
mysql>   select * from runoob_transaction_test;   # 由於回滾因此數據沒有插入
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
相關文章
相關標籤/搜索