(一)什麼是事物?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來實現
二、直接用 SET 來改變 MySQL 的自動提交模式:
例子:
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)