mysql 多個select需要放入一個事務嗎?
阿新 • • 發佈:2018-06-07
from ali 臟讀 trac atom 設置 存在 .get ria
個人覺得多個select時,不用放入一個事務,select查詢本身不需要事務提交。而如果在修改數據時,不提交事務,則會修改失敗。select只是用來進行查詢操作,不需要事務回滾,因為select不會對數據庫的產生持久化的修改,沒有必要在數據發生不一致的時候進行回滾。如果要防止數據的不一致情況,可以通過修改事務的隔離級別實現。
事務的隔離級別: 多個線程開啟各自的事務操作數據庫中數據時,數據庫系統要負責隔離操作,以保證各個線程在獲取數據時的準確性。也就是說,隔離級別就是對對事務並發控制的等級。如果事務不考慮隔離性會引發以下問題: (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 如果設置成了這種級別,那麽數據庫就變成了單線程訪問的數據庫,導致性能降低很多。
四種隔離級別及特點:
這裏有個事務隔離級別的例子,寫的很好:http://blog.163.com/mr_liuyong/blog/static/1234243762012511105645731/
第一次寫博客,還請大家多多支持
今天同事問了個問題:在多個select的時候,用不用放入同一個事務?
首先先看個例子:
[java] view plain copy print?
- public class JDBCClient {
- public static void main(String[] args) {
- Connection conn = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- conn = DriverManager.getConnection("jdbc:mysql://localhost/test"
- if(conn != null) {
- //將本次會話的事務隔離級別設置為TRANSACTION_READ_COMMITTED,mysql默認的是REPEATABLE_READ
- conn.setTransactionIsolation(2);
- //關閉事務的自動提交
- conn.setAutoCommit(false);
- PreparedStatement ps = conn.prepareStatement("select student_no from student where student_id = 1 "
- ResultSet rs = ps.executeQuery();
- while(rs.next()) {
- System.out.println(rs.getString(1));
- }
- //設置斷點,並將數據庫中執行 update student set student_no = ‘新的值‘ where student_id = 1;然後繼續執行
- System.out.println("-----------"
- rs = ps.executeQuery();
- while(rs.next()) {
- //這裏打印出新賦值的值
- System.out.println(rs.getString(1));
- }
- //提交事務
- //conn.commit();
- }
- } catch (Exception e) {
- e.printStackTrace();
- if(conn != null) {
- try {
- conn.rollback();
- } catch (SQLException e1) {
- e1.printStackTrace();
- }
- }
- }
- }
- //註:如果應用mysql默認的事務隔離級別,則兩次打印出的內容一致;
- }
個人覺得多個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/
mysql 多個select需要放入一個事務嗎?