mysql 多個select需要放入一個事務嗎?


第一次寫博客,還請大家多多支持微笑



今天同事問了個問題:在多個select的時候,用不用放入同一個事務?

首先先看個例子:

  1. public class JDBCClient {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Connection conn = null;  
  5.         try {  
  6.               
  7.             Class.forName("com.mysql.jdbc.Driver");  
  8.             conn = DriverManager.getConnection("jdbc:mysql://localhost/test","root","123456");  
  9.               
  10.             if(conn != null) {  
  11.                 //將本次會話的事務隔離級別設置為TRANSACTION_READ_COMMITTED,mysql默認的是REPEATABLE_READ  
  12.                 conn.setTransactionIsolation(2);  
  13.                 //關閉事務的自動提交  
  14.                 conn.setAutoCommit(false);  
  15.                   
  16.                 PreparedStatement ps = conn.prepareStatement("select student_no from student where student_id = 1 ");  
  17.                 ResultSet rs = ps.executeQuery();  
  18.                 while(rs.next()) {  
  19.                     System.out.println(rs.getString(1));  
  20.                 }  
  21.                   
  22.                 //設置斷點,並將數據庫中執行 update student set student_no = '新的值' where student_id = 1;然后繼續執行  
  23.                 System.out.println("-----------");  
  24.                 rs = ps.executeQuery();  
  25.                 while(rs.next()) {  
  26.                     //這里打印出新賦值的值  
  27.                     System.out.println(rs.getString(1));  
  28.                 }  
  29.                                   
  30.                 //提交事務  
  31.                 //conn.commit();  
  32.             }  
  33.         } catch (Exception e) {  
  34.             e.printStackTrace();  
  35.             if(conn != null) {  
  36.                 try {  
  37.                     conn.rollback();  
  38.                 } catch (SQLException e1) {  
  39.                     e1.printStackTrace();  
  40.                 }  
  41.             }  
  42.         }  
  43.     }  
  44.     //注:如果應用mysql默認的事務隔離級別,則兩次打印出的內容一致;  
  45. }  

個人覺得多個select時,不用放入一個事務,select查詢本身不需要事務提交。而如果在修改數據時,不提交事務,則會修改失敗。
select只是用來進行查詢操作,不需要事務回滾,因為select不會對數據庫的產生持久化的修改,沒有必要在數據發生不一致的時候進行回滾。如果要防止數據的不一致情況,可以通過修改事務的隔離級別實現。

事務:

事務的四大特性 (ACID)
       1、原子性(Atomicity)  事務是一個不可分割的工作單位,事務中的操作要么都發生,要么都不發生。
       2、一致性(Consistency) 事務前后數據的完整性必須保持一致。
       3、隔離性(Isolation) 多個用戶並發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所干擾,多個並發事務之間的數據要相互隔離。
       4、持久性(Durability) 一個事務一旦被提交,它對數據庫中的數據改變就是永久性的。

事務的隔離級別:
       多個線程開啟各自的事務操作數據庫中數據時,數據庫系統要負責隔離操作,以保證各個線程在獲取數據時的准確性。也就是說, 隔離級別就是對對事務並發控制的等級。如果事務不考慮隔離性會引發以下問題:
      (1)臟讀:
       指一個事務讀取了另外一個事務未提交的數據。比如 A 向 B 購買商品,如果 B 的事務隔離級別為最低的 read uncommitted,那么當 A 執行了 update account set money=money+100 where name='B';以后並沒有提交數據的時候,B 進行了 select money from account where name='B';查詢賬戶的操作,由於 B 的 事務隔離級別最低,所以導致了臟讀,讀取到了 A 沒有提交的數據,當 A 執行了 rollback 回滾命令以后,B 再查詢賬戶,就發現先前增加的 100 元消失了。為了避免臟讀,我們可以將事務的隔離級別設置為:read committed。
      (2)不可重復讀:
       在一個事務內讀取到了表中的某一行數據,多次讀取結果不同。不可重復讀和臟讀的區別是:臟讀是讀取前一事務未提交的數據,不可重復讀是重新讀取了前一個事務已提交的數據。比如還是剛才的情景,當 B 將自己的事務隔離級別設置了 read committed 時,可以避免臟讀,也就是別人沒有提交的數據是讀不到的。但是如果 A 將數據提交了,執行了 commit 命令后,B 在這個當前事務內再次查詢賬戶的時候,就發現賬戶多了 100 元,這種情況看似是符合邏輯的,但是我們這里說到的不可重復讀是指在這個當前事務內,不可以發生兩次讀取操作結果不一致的可能性,我們要保證在一個事務中,我們多次從數據庫獲取的數據應該是一致的,這樣才能保證我們進行數據操作的可靠性。為了避免這個為題,我們可以將數據庫的事務隔離級別設置為:repeatable read,這樣就保證了在一個事務中,每次讀取到數據都是一致的。
      (3)虛讀 ( 幻讀 )
       在一個事務內讀取到了別的事務插入的數據,導致前后讀取不一致。和不可重復讀的區別是:不可重復讀是讀取到了別人對表中的某一條記錄進行了修改,導致前后讀取的數據不一致。  虛讀是前后讀取到表中的記錄總數不一樣,讀取到了其它事務插入的數據。比如現在有 A 和 B 兩個應用程序,他們並發訪問了數據庫中的某一張表,假設表中有 3 條記錄,B 執行查詢操作, 第一次查詢表得到了 3 條記錄。此時 A 對表進行了修改,增加了一條記錄,當 B 再次查詢表的時候,發現多了一條數據。這種情況就造成了 B 的虛讀。但是虛讀是不一定每次都發生的,這種情況是不確定的。為了避免虛讀,我們可以將 事務隔離級別設置為 serializable 如果設置成了這種級別,那么數據庫就變成了單線程訪問的數據庫,導致性能降低很多。

四種隔離級別及特點:
隔離級別 是否存在臟讀 是否存在不可重復讀 是否存在幻讀
Read UnCommit(未提交讀) Y Y Y
Read Commit(提交讀) N Y Y
Repeated Reader(可重復讀) N N Y
Serializable Reader(序列化讀) N N N

這里有個事務隔離級別的例子,寫的很好: http://blog.163.com/mr_liuyong/blog/static/1234243762012511105645731/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM