java面試-資料庫事務詳解
什麼是『事務』?
事務就是一組具有原子性的操作,這一組操作要麼全都正確執行,要麼全都不執行。
事務能保證資料庫從一種一致性狀態轉換為另一種一致性狀態。
事務的四大特性ACID
1. 原子性
原子性指的是事務是一個不可分割的操作,要麼全都正確執行,要麼全都不執行。
2. 一致性
事務開始前和事務結束後,資料庫的完整性約束沒有被破壞。
3. 隔離性
事務的執行是相互獨立的,它們不會相互干擾,一個事務不會看到另一個正在執行過程中的事務的資料。
4. 永續性
事務結束後,事務的結果必須是永久儲存的。即使資料庫發生崩潰,在資料庫恢復後事務提交的結果仍然不會丟失。
PS:事務只能保證資料庫的高可靠性,即資料庫本身發生問題後,事務提交後的資料仍然能恢復;而如果不是資料庫本身的故障,如硬碟損壞了,那麼事務提交的資料可能就丟失了。這屬於『高可用性』的範疇。因此,事務只能保證資料庫的『高可靠性』,而『高可用性』需要整個系統共同配合實現。
事務的分類
1. 扁平事務
- 它是實際生產環境中最常用、最簡單的事務型別。
- 事務從BEGIN WORK開始,從COMMIT WORK或ROLLBACK WORK結束。
- 缺點:發生錯誤時回滾到事務的起始位置,無法回滾部分操作。而回滾所有的操作開銷太大。
2. 帶有儲存點的扁平事務
這種事務能設定多個儲存點,當發生錯誤時可以回滾到事務中指定的儲存點,而不需要將整個事務回滾。
3. 鏈事務
4. 巢狀事務
5. 分散式事務
資料庫併發訪問會出現的問題
1. 更新丟失
當有兩個併發執行的事務,更新同一行資料,那麼有可能一個事務會把另一個事務的更新覆蓋掉。
當資料庫沒有加任何鎖操作的情況下會發生。
2. 髒讀
一個事務讀到另一個尚未提交的事務中的資料。
該資料可能會被回滾從而失效。
如果第一個事務拿著失效的資料去處理那就發生錯誤了。
3. 不可重複讀
不可重複度的含義:一個事務對同一行資料讀了兩次,卻得到了不同的結果。它具體分為如下兩種情況:
1. 虛讀:在事務1兩次讀取同一記錄的過程中,事務2對該記錄進行了修改,從而事務1第二次讀到了不一樣的記錄。
2. 幻讀:事務1在兩次查詢的過程中,事務2對該表進行了插入、刪除操作,從而事務1第二次查詢的結果發生了變化。
與『髒讀』的區別?
髒讀讀到的是尚未提交的資料,而不可重複讀讀到的是已經提交的資料,只不過在兩次讀的過程中資料被另一個事務改過了。
事務的隔離級別
資料庫事務的隔離級別有4個,由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個級別可以逐個解決髒讀 、不可重複讀 、幻讀 這幾類問題。
1. Read uncommitted 讀未提交
在該級別下,一個事務對一行資料修改的過程中,不允許另一個事務對該行資料進行修改,但允許另一個事務對該行資料讀。
因此本級別下,不會出現更新丟失,但會出現髒讀、不可重複讀。
2. Read committed 讀提交
在該級別下,未提交的寫事務不允許其他事務訪問該行,因此不會出現髒讀;但是讀取資料的事務允許其他事務的訪問該行資料,因此會出現不可重複讀的情況。
3. Repeatable read 重複讀
在該級別下,讀事務禁止寫事務,但允許讀事務,因此不會出現同一事務兩次讀到不同的資料的情況(不可重複讀),且寫事務禁止其他一切事務。
4. Serializable 序列化
該級別要求所有事務都必須序列執行,因此能避免一切因併發引起的問題,但效率很低。
隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed。它能夠避免髒讀取,而且具有較好的併發效能。儘管它會導致不可重複讀、幻讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲觀鎖或樂觀鎖來控制。