A. spring mvc 怎麼樣設置mysql事物隔離級別
先來總體說一下我對這個問題的理解,用一句話概括:
資料庫是可以控制事務的傳播和隔離級別的,Spring在之上又進一步進行了封裝,可以在不同的項目、不同的操作中再次對事務的傳播行為和隔離級別進行策略控制。
注意:Spring不僅可以控制事務傳播行為(PROPAGATION_REQUIRED等),還可以控制事務隔離級別(ISOLATION_READ_UNCOMMITTED等)。
(以下是個人理解,如果有瑕疵請及時指正)
下面我具體解釋一下:
為了大家能夠更好的理解,先來明確幾個知識點:
事務的傳播行為:簡單來說就是事務是手動提交還是自動提交,事務什麼時候開始,什麼時候提交。
事務的隔離級別:簡單來說,就四個,提交讀,提交讀,重復讀,序列化讀。
首先我來描述一下,資料庫(mysql)層面上對於事務傳播行為和隔離級別的配置和實驗方法:
資料庫層面(採用命令行):其實mySql命令行很簡單,希望實驗操作一下:
//連接資料庫,我這里是本地,後面是用戶名密碼,不要打分號,如果指令不行,配置下環境變數,網上有很多。
1. cmd中執行:mysql -hlocalhost -uroot -pmysql
//查看本地資料庫事務傳播行為是手動提交(0),還是自動提交(1)。
2.select @@autocommit;
//如果是0,希望設置為手動提交,這里其實是設置本對話的autocommit,因為如果你再開一個cmd,發現還是沒改回來,如果想修改全局的,網上有global方法。
3.set @@autocommit=0;
//然後查詢本地資料庫中的一條記錄,我本地資料庫為test1;
4.use test1;
5.select * from task where taskid=1;
//同時新開一個窗口cmd,連接資料庫,並且修改這條記錄,update語句我就不寫了,或者直接修改資料庫本條記錄。
//再次執行select * from task where taskid=1;發現值沒變。OK因為此時資料庫隔離級別為repeatable read 重復讀,因為mysql默認的隔離級別是重復讀。
//修改資料庫隔離級別
6.set global transaction isolation level read committed;
//查看一下,可能需要重新連接一下
7.select @@tx_isolation;
//這時在執行一下4,5操作,發現值變了,ok。因為已經改變了資料庫隔離級別,發生了重復讀出不同數據的現象。
(以上操作希望有不明白的上網自學一下,很有用,先把資料庫隔離級別弄明白了)
然後再來講一下,Spring對事務傳播行為和隔離級別的二次封裝。
因為不同項目可能在一個mysql的不同資料庫上,所以可以在項目中配置資料庫的傳播行為和隔離級別:
關於spring的傳播行為(PROPAGATION_REQUIRED、PROPAGATION_REQUIRED等),我《資料庫隔離級別(mysql+Spring)與性能分析 》文章中有講,網上也有很多相關資料,我就不說了。
關於spring的事務隔離級別與資料庫的一樣,也是那四個,多了一個default,我也不仔細講了。
下面主要講一下spring的配置方法:
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED</prop>
</props>
就以find為例,可以配置這么配置,前面是控制傳播行為,後面是控制事務隔離級別的。那麼這時哪怕資料庫層面上是重復讀,但是還是以這里為准,你會發現在同一個事務中兩次查詢的結果是不一樣的。
最後掃除一個盲區,readonly這個屬性,是放在傳播行為中的,一般書都這么歸類,我也嘗試了一下,readonly並不能影響資料庫隔離級別,只是配置之後,不允許在事務中對資料庫進行修改操作,僅此而已。
B. mysql隔離級別
MySQL 中事務的隔離級別一共分為四種,分別如下:
序列化(SERIALIZABLE):如果隔離級別為序列化,則用戶之間通過一個接一個順序地執行當前的事務,這種隔離級別提供了事務之間最大限度的隔離。
可重復讀(REPEATABLE READ):在可重復讀在這一隔離級別上,事務不會被看成是一個序列。不過,當前正在執行事務的變化仍然不能被外部看到,也就是說,如果用戶在另外一個事務中執行同條 SELECT 語句數次,結果總是相同的。(因為正在執行的事務所產生的數據變化不能被外部看到)。
提交讀(READ COMMITTED):READ COMMITTED 隔離級別的安全性比 REPEATABLE READ 隔離級別的安全性要差。處於 READ COMMITTED 級別的事務可以看到其他事務對數據的修改。也就是說,在事務處理期間,如果其他事務修改了相應的表,那麼同一個事務的多個 SELECT 語句可能返回不同的結果。
未提交讀(READ UNCOMMITTED):READ UNCOMMITTED 提供了事務之間最小限度的隔離。除了容易產生虛幻的讀操作和不能重復的讀操作外,處於這個隔離級的事務可以讀到其他事務還沒有提交的數據,如果這個事務使用其他事務不提交的變化作為計算的基礎,然後那些未提交的變化被它們的父事務撤銷,這就導致了大量的數據變化。
應用環境
與其他的大型資料庫例如Oracle、DB2、SQL Server等相比,MySQL自有它的不足之處,但是這絲毫也沒有減少它受歡迎的程度。對於一般的個人使用者和中小型企業來說,MySQL提供的功能已經綽綽有餘,而且由於 MySQL是開放源碼軟體,因此可以大大降低總體擁有成本。
C. 事務隔離級別有哪些
事務的隔離級別有4種,由低到高分別為Read uncommitted 、Read committed 、Repeatable read 、Serializable 。事物的並發操作中可能休閑臟讀,不可重復讀,幻讀。
1、第一種隔離級別:Read uncommitted(讀未提交)
如果一個事務已經開始寫數據,則另外一個事務不允許同時進行寫操作,但允許其他事務讀此行數據,該隔離級別可以通過「排他寫鎖」,但是不排斥讀線程實現。這樣就避免了更新丟失,卻可能出現臟讀,也就是說事務B讀取到了事務A未提交的數據。
解決了更新丟失,但還是可能會出現臟讀。
2、第二種隔離級別:Read committed(讀提交)
如果是一個讀事務(線程),則允許其他事務讀寫,如果是寫事務將會禁止其他事務訪問該行數據,該隔離級別避免了臟讀,但是可能出現不可重復讀。事務A事先讀取了數據,事務B緊接著更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
解決了更新丟失和臟讀問題。
3、第三種隔離級別:Repeatable read(可重復讀取)
可重復讀取是指在一個事務內,多次讀同一個數據,在這個事務還沒結束時,其他事務不能訪問該數據,這樣就可以在同一個事務內兩次讀到的數據是一樣的,因此稱為是可重復讀隔離級別,讀取數據的事務將會禁止寫事務,寫事務則禁止任何其他事務,這樣避免了不可重復讀和臟讀,但是有時可能會出現幻讀。
讀取數據的事務可以通過「共享讀鏡」和「排他寫鎖」實現。
解決了更新丟失、臟讀、不可重復讀、但是還會出現幻讀。
4、第四種隔離級別:Serializable(可序化)
提供嚴格的事務隔離,它要求事務序列化執行,事務只能一個接著一個地執行,但不能並發執行,如果僅僅通過「行級鎖」是無法實現序列化的,必須通過其他機制保證新插入的數據不會被執行查詢操作的事務訪問到。
序列化是最高的事務隔離級別,同時代價也是最高的,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免臟讀、不可重復讀,還避免了幻讀。
事務的基本要素(ACID)
1、原子性(Atomicity):事務開始後所有操作,要麼全部做完,要麼全部不做,不可能停滯在中間環節。事務執行過程中出錯,會回滾到事務開始前的狀態,所有的操作就像沒有發生一樣。也就是說事務是一個不可分割的整體,就像化學中學過的原子,是物質構成的基本單位。
2、一致性(Consistency):事務開始前和結束後,資料庫的完整性約束沒有被破壞 。比如A向B轉賬,不可能A扣了錢,B卻沒收到。
3、隔離性(Isolation):同一時間,只允許一個事務請求同一數據,不同的事務之間彼此沒有任何干擾。比如A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉賬。
4、持久性(Durability):事務完成後,事務對資料庫的所有更新將被保存到資料庫,不能回滾。
以上內容參考:事務隔離級別 - 網路