事務特性,事務的隔離級別,並發事務可能出現的問題,spring事務 數據庫鎖
1.0 事務特性(ACID)
Atomicity:原子性,一個事務不可以被拆分
Consistency:一致性,在事務執行前數據庫的數據處於正確的狀態,而事務執行完成後數據庫的數據還是處於正確的狀態,即數據完整性約束沒有被破壞;比如我們做銀行轉賬的相關業務,A轉賬給B,要求A轉的錢B一定要收到。如果A轉了錢而B沒有收到,那麽數據庫數據的一致性就得不到保障,在做高並發業務時要註意合理的設計。
Isolation:隔離性,並發事務執行之間無影響,在一個事務內部的操作對其他事務是不產生影響,這需要事務隔離級別來指定隔離性;
Durability:持久性,事務一旦執行成功,它對數據庫的數據的改變必須是永久的,不會因各種異常導致數據不一致或丟失。
1.1 事務的隔離級別
READ_UNCOMMITTED 會出現臟讀、不可重復讀、幻讀 ( 隔離級別最低,並發性能高 )
READ_COMMITTED 會出現不可重復讀、幻讀問題(鎖定正在讀取的行)
REPEATABLE_READ 會出幻讀(鎖定所讀取的所有行)
SERIALIZABLE 保證所有的情況不會發生(鎖表)
大多數數據庫的默認隔離級別為: Read Commited,如Sql Server , Oracle. |
1.2事務並發引起的問題
1.2.1臟讀:數據已修改事務沒提交,另一事務讀取到未提交的數據!(事務沒提交另一事務就讀到未提交的數據)
1.2.2不可重復讀:同一事務兩次讀取數據不一樣;第一個事務讀去數據,第二個事務修改數據提交,第一個事務再一次讀取數據,這樣第一個事務兩次讀取的數據將不一致。
1.2.3幻讀:兩個事務,第一個事務將所有行的數據都修改了,第二個事務將插入一條數據提交,第1個事務提交發現有一條數據並沒有修改。
1.2.4第一類丟失(回滾丟失):
當2個事務更新相同的數據源,如果第一個事務被提交,而另外一個事務卻被撤銷,那麽會連同第一個事務所做的跟新也被撤銷。也就是說第一個事務做的跟新丟失了
1.2.5第二類更新丟失(覆蓋丟失)
加深理解:
- 不可重復讀和幻讀的區別
兩者都是相同事務兩次讀取不一致,一個是被另外事務修改讀取不一致,一個是被另外事務插入/刪除讀取不一致。
2.spring事務
引用文章:http://blog.csdn.net/it_man/article/details/5074371
2.1 事務傳播行為(Transaction Propagation Behavior)
事務在方法中傳播。
- PROPAGATION_REQUIRED
- RROPAGATION_REQUIRES_NEW
- PROPAGATION_NESTED
- PROPAGATION_SUPPORTS
- PROPAGATION_NOT_SUPPORTED
- PROPAGATION_NEVER
- PROPAGATION_MANDATORY
首先要明確的是,事務是從哪裏來?傳播到哪裏去?答案是,從方法 A 傳播到方法 B。Spring 解決的只是方法之間的事務傳播,那情況就多了,比如:
- 方法 A 有事務,方法 B 也有事務。
- 方法 A 有事務,方法 B 沒有事務。
- 方法 A 沒有事務,方法 B 有事務。
- 方法 A 沒有事務,方法 B 也沒有事務。
假設事務從方法 A 傳播到方法 B,您需要面對方法 B,問自己一個問題:
方法 A 有事務嗎?
- 如果沒有,就新建一個事務;如果有,就加入當前事務。這就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默認事務傳播行為,適合絕大多數情況。
- 如果沒有,就新建一個事務;如果有,就將當前事務掛起。這就是 RROPAGATION_REQUIRES_NEW,意思就是創建了一個新事務,它和原來的事務沒有任何關系了。
- 如果沒有,就新建一個事務;如果有,就在當前事務中嵌套其他事務。這就是 PROPAGATION_NESTED,也就是傳說中的“嵌套事務”了,所嵌套的子事務與主事務之間是有關聯的(當主事務提交或回滾,子事務也會提交或回滾)。
- 如果沒有,就以非事務方式執行;如果有,就使用當前事務。這就是 PROPAGATION_SUPPORTS,這種方式非常隨意,沒有就沒有,有就有,有點無所謂的態度,反正我是支持你的。
- 如果沒有,就以非事務方式執行;如果有,就將當前事務掛起。這就是 PROPAGATION_NOT_SUPPORTED,這種方式非常強硬,沒有就沒有,有我也不支持你,把你掛起來,不鳥你。
- 如果沒有,就以非事務方式執行;如果有,就拋出異常。這就是 PROPAGATION_NEVER,這種方式更猛,沒有就沒有,有了反而報錯,確實夠牛的,它說:我從不支持事務!
- 如果沒有,就拋出異常;如果有,就使用當前事務。這就是 PROPAGATION_MANDATORY,這種方式可以說是牛逼中的牛逼了,沒有事務直接就報錯,確實夠狠的,它說:我必須要有事務!
2.2 spring 事務隔離級別
DEFAULT 使用數據庫設置的隔離級別 ( 默認 ) ,由 DBA 默認的設置來決定隔離級別 .
READ_UNCOMMITTED 會出現臟讀、不可重復讀、幻讀 ( 隔離級別最低,並發性能高 )
READ_COMMITTED 會出現不可重復讀、幻讀問題(鎖定正在讀取的行)
REPEATABLE_READ 會出幻讀(鎖定所讀取的所有行)
SERIALIZABLE 保證所有的情況不會發生(鎖表)
不可重復讀的重點是修改 :
同樣的條件 , 你讀取過的數據 , 再次讀取出來發現值不一樣了
幻讀的重點在於新增或者刪除
同樣的條件 , 第 1 次和第 2 次讀出來的記錄數不一樣
1、Serializable:最嚴格的級別,事務串行執行,資源消耗最大; 2、REPEATABLE READ:保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的數據。避免了“臟讀取”和“不可重復讀取”的情況,但是帶來了更多的性能損失。 3、READ COMMITTED:大多數主流數據庫的默認事務等級,保證了一個事務不會讀到另一個並行事務已修改但未提交的數據,避免了“臟讀取”。該級別適用於大多數系統。 4、Read Uncommitted:保證了讀取過程中不會讀取到非法數據。隔離級別在於處理多事務的並發問題。 |
2.3 spring 事務管理的方式
聲明式事務:TransactionProxyFactoryBean 在spring 配置文件中進行配置或者使用註解
編程式事務:TransactionTemplate PlatformTransactionManager
3 .數據庫鎖
- 悲觀鎖:利用數據庫本身的鎖機制實現。通過上面對數據庫鎖的了解,可以根據具體業務情況綜合使用事務隔離級別與合理的手工指定鎖的方式比如降低鎖的粒度等減少並發等待。
- 樂觀鎖:利用程序處理並發。原理都比較好理解,基本一看即懂。方式大概有以下3種
- 對記錄加版本號.
- 對記錄加時間戳.
- 對將要更新的數據進行提前讀取、事後對比。
不論是數據庫系統本身的鎖機制,還是樂觀鎖這種業務數據級別上的鎖機制,本質上都是對狀態位的讀、寫、判斷。
http://www.cnblogs.com/zhouqianhua/archive/2011/04/15/2017049.html
參考文章:
http://www.codeweblog.com/%E4%BA%8B%E5%8A%A1-%E9%94%81-spring%E6%94%AF%E6%8C%81/
http://blog.csdn.net/it_man/article/details/5074371
http://www.cnblogs.com/zhouqianhua/archive/2011/04/15/2017049.html
http://www.cnblogs.com/yldIndex/p/spring_Transactional.html
http://blog.csdn.net/yangchangyong0/article/details/51996708
事務特性,事務的隔離級別,並發事務可能出現的問題,spring事務 數據庫鎖