事务常规理解
一:事務四大特性
- 原子性(Atomicity);事務必須是一個不可分割的整體,就像我們在化學課里學到的原子,原子是構成物質的最小單位。于是,人們就歸納出事務的第一個特性,
- 一致性(Consistency):也就是說,執行完數據庫操作后,數據不會被破壞。打個比方,如果從 A 賬戶轉賬到 B 賬戶,不可能因為 A
賬戶扣了錢,而 B 賬戶沒有加錢吧。 - 隔離性:當我們編寫了一條 update 語句,提交到數據庫的一剎那間,有可能別人也提交了一條 delete
語句到數據庫中。也許我們都是對同一條記錄進行操作,可以想象,如果不稍加控制,就會出大麻煩來。我們必須保證數據庫操作之間是“隔離”的 - 持久性(Durability):數據永久地存放在磁盤中,這個也算事務的一條特性
注:這 4 條特性,是事務管理的基石,一定要透徹理解。此外還要明確,這四個家伙當中,誰才是老大?
其實想想也就清楚了:原子性是基礎,隔離性是手段,持久性是目的,真正的老大就是一致性。數據不一致了,就相當于“江湖亂套了”。所以說,這三個小弟都是跟著“一致性”這個老大混,為他全心全意服務。
這四個家伙當中,其實最難理解的反倒不是一致性,而是隔離性。因為它是保證一致性的重要手段,是工具,使用它不能有半點差池,否則后果自負!
二:常規數據問題
三類數據讀問題1.Dirty Read(臟讀)2.Unrepeatable Read(不可重復讀)3.Phantom Read(幻讀) 兩類數據更新問題1.第一類丟失更新2.第二類丟失更新5種問題可以自行百度;
簡單點就是:
1.臟讀:事務 A 讀取了事務 B 未提交的數據,并在這個基礎上又做了其他操作。
兩個事務都做了修改操作,做完后都做了一次查詢,事務沒有隔離開,被互相影響到了;
2.不可重復讀:事務 A 讀取了事務 B 已提交的更改數據。
3.幻讀:事務 A 讀取了事務 B 已提交的新增數據。
第一條是堅決抵制的,后兩條在大多數情況下可不作考慮。
第一類更新可以理解為:
事務A,事務b都做了寫操作,A因為回滾覆蓋了B
第二類更新可以理解為:
事務B后提交的,吧事務A覆蓋了;
理論上,第一種更新問題不允許出現,,第二類,一般數據庫靠鎖來等待,或者你的sql是個覆蓋的sql
三:數據庫事務和鎖
數據庫四個隔離級別:
事務隔離級別(Transaction Isolation Level) 1.READ_UNCOMMITTED2.READ_COMMITTED3.REPEATABLE_READ4.SERIALIZABLE 從上往下,級別越來越高,并發性越來越差,安全性越來越高,反之則反。
數據庫鎖也是保證數據庫數據不發生紊亂的法則之一:
例如,orcal:
讀操作不影響:一般查詢共享鎖;加入for update 會鎖響應數據,不希望別人來更新;
修改某條數據,一般會加行鎖,看是否用到索引,行鎖與表鎖的切換;
新增某條記錄,一般加表鎖
可參考:orcal數據庫的鎖
四:java程序中的事務、以及鎖
第三步保證的數據庫中事務的處理,以及不影響數據,
但是程序中,如何在數據庫正常的情況下,自己程序導致的數據紊亂呢;
4.1事務的傳播行為:
也可以理解為,一次請求,會訪問多個方法,多個方法直接的事務是怎么影響的;
例如:
從方法 A訪問方法 B。Spring 解決的只是方法之間的事務傳播:
假如方法B出現了問題,如果方法a有寫操作,會有什么影響呢?
報錯還是一起回滾呢?一起回滾的花,主事務是A還是B呢?
默認事務傳播行為: PROPAGATION_REQUIRED ,有就加入;
Spring 給我們帶來了事務傳播行為,這確實是一個非常強大而又實用的功能。除此以外,也提供了一些小的附加功能,比如:
1.事務超時(Transaction Timeout):為了解決事務時間太長,消耗太多的資源,所以故意給事務設置一個最大時常,如果超過了,就回滾事務。
2.只事務(Readonly Transaction):為了忽略那些不需要事務的方法,比如讀取數據,這樣可以有效地提高一些性能。
注解事務比較方便:只需:
@Transactional public void xxx() { ... }4.2 多線程情況下的數據問題
4.1可以理解為單線程,或者多線程情況下,一次請求,各種操作事務如何嵌套的,如果出現問題,事務回滾
多線程情況下,一般都是私有變量,或者常量,或者每次查詢操作,最后一步統一實現寫入數據庫操作,事務最后一次commit提交;
還有一種情況就是,多個線程共用一個公共數據了,并且需要修改,,這這時候,就需要用到程序上的,同步、鎖、等api操作了,保證數據不能出現問題
:額外在補充4.2鎖
總結
- 上一篇: JavaEE——Spring学习笔记03
- 下一篇: web of science 数据库都包