JDBC核心技術之(二)事物

6.jdbc事物
什麼是事物:
事物就是邏輯上的一組操作,要麼成功,要麼失敗!(比如轉賬 A 給 B 轉賬,A轉出去了,B沒收到,那麼就不應該算成功,而是應該全部失敗.)
事物的特性:
      •  原子性:意思是不可以分割
      • 一致性:意思就是事物從一個狀態到另一個狀態,應該是一致的,比如說轉賬(A有1000元,B有1000元,他們一共2000元;現在A轉給B 500元,那麼轉賬之後A 有500元,B 有1500元[中間不考慮手續費什麼的..],這樣他們還是 2000元,就是前後一致的。)
      • 隔離性:意思一個事物一旦開啓,就應該不受其他事物的影響(還是用轉賬來舉例: A去ATM上查有1000元,在查的同時,B給A轉了 500元,但是現在A 還沒有退出當前事物,因此A 就不應該知道B 給他轉了500元。)
      • 永久性: 意思就是一旦事物提交,就應該永久的存起來
如何開始事物?
               一般來說,事物都是默認開啓的,我們要自己來控制事物,一般涉及到如下步驟                                   
      • 設置不默認開啓事物
      • 提交事物
      • 事物錯誤,回滾
來看看代碼
@Test
      public void test_trans(){
           try {
              Class .forName( "com.mysql.jdbc.Driver");
              Connection connection = DriverManager.getConnection( url, user, password);
              connection .setAutoCommit( false);//設置不默認開啓事物
              PreparedStatement ps = connection.prepareStatement( "update test set name='000' where id=1");
              ps .executeUpdate();
               int i = 1 /0; //錯誤
              ps = connection. prepareStatement("update test set name='222' where id=2");
              ps .executeUpdate();
              connection .commit(); //事物提交
           } catch (Exception e) {
              e .printStackTrace();
               try {
                    connection.rollback ();//事物回滾
               } catch (SQLException e1) {
                   e1 .printStackTrace();
               }
              
           }finally {
               //關閉資源
           }
          
      }

如果步驟比較多,然後不確定有一個步驟是否會有錯,這時候可以設置回滾點
看下代碼
@Test
      public void test_trans1(){
          Savepoint sp  = null;
           try {
              Class .forName( "com.mysql.jdbc.Driver");
              Connection connection = DriverManager.getConnection( url, user, password);
              connection .setAutoCommit( false);//設置不默認開啓事物
              PreparedStatement ps = connection.prepareStatement( "update test set name='000' where id=1");
              ps .executeUpdate();
              sp = connection. setSavepoint();//設置回滾點
              
               int i = 1 /0; //錯誤
              ps = connection. prepareStatement("update test set name='222' where id=2");
              ps .executeUpdate();
              
           } catch (Exception e) {
              e .printStackTrace();
               try {
                    connection.rollback (sp); //事物回滾
               } catch (SQLException e1) {
                   e1 .printStackTrace();
               }
              
           }finally {
               try {
                    connection.commit ();
               } catch (SQLException e) {
                   e .printStackTrace();
               }//事物提交
               //關閉資源
           }
          
      }

我自己的建議是能不用回滾點就不用它。

事物的隔離級別
TRANSACTION_READ_UNCOMMITTED
          指示可以發生髒讀 (dirty read)、不可重複讀和虛讀 (phantom read) 的常量。
TRANSACTION_READ_COMMITTED
          指示不可以發生髒讀的常量;不可重複讀和虛讀可以發生。
TRANSACTION_REPEATABLE_READ
          指示不可以發生髒讀和不可重複讀的常量;虛讀可以發生。
TRANSACTION_SERIALIZABLE
          指示不可以發生髒讀、不可重複讀和虛讀的常量。
java.sql.Connection
public static final int TRANSACTION_READ_COMMITTED 2
public static final int TRANSACTION_READ_UNCOMMITTED 1
public static final int TRANSACTION_REPEATABLE_READ 4
public static final int TRANSACTION_SERIALIZABLE 8

這幾個隔離級別的髒讀,不可重複讀,幻讀(虛讀)到底是什麼意思?

在事務管理中違反ACID特性的3個問題:髒讀取、不可重複讀和幻影行。如果存在多個併發的事務在運行,而這些事務操作了同一個數據來完成他們的任務,就會導致3個問題的存在。要解決它們,就必須在事務之間定義合適的隔離級別。事務之間存在的3個問題是:

髒讀取 (Dirty read)

當一個事務讀取了另一個事務尚未提交的更新,就叫髒讀取。在另一個事務回滾的情況下,當前事務所讀取的另一個事務的數據就是無效的。

不可重複讀取(Nonrepeatable read)

在一個事務中執行多次同樣的查詢操作,但每次查詢的結果都不一樣,就叫做不可重複讀取,通常這種情況是由於數據在二次查詢之間被另一個併發的事務所修改。

幻讀(Phantom rows)

這是對事務危害最小的一個問候,它類似不可重複讀取,也是一個事務的更新結果影響到另一個事務問題。但是它不僅影響另一個事務查詢結果,而且還會使查詢語句返回一些不同的行錄行。

這3個問題危害程度依次爲:髒讀取最大、不可重複讀取其次、幻讀最小。


如何查詢數據庫的默認事物級別:
mysql>
mysql>  select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
默認的是:指示不可以發生髒讀和不可重複讀的常量;虛讀可以發生
一般這個級別基本上能夠滿足我們的需求了
下面我們來試試測試下:
先修改數據庫的事物級別爲最低的;


修改後的結果:
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)
先看下數據庫
同時兩個事物再跑:



先測試髒讀


這個時候一個事物(A)在查詢,開始查詢出來money=1000,然後另一個事物(B)修改價格,這時候事物(A)再次查詢,就變成了money=1500,讀取到了B還沒有提交的數據叫髒讀。

同時也出現了另一個錯誤,叫不可重複讀,事物A前後讀取的數據不一樣。

還有一個幻讀,這個不好測試,就在這裏不測了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章