生活随笔
收集整理的這篇文章主要介紹了
大数据WEB阶段(十八)数据库事务
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
數(shù)據(jù)庫事務
一、概述
事務的概念
事務是指邏輯上的一組操作 , 組成這組操作的各個單元 , 要么全部成功 , 要么全部失敗 。 如:銀行轉(zhuǎn)賬。。
轉(zhuǎn)賬核心操作其實就是兩條sql ,兩條都執(zhí)行成功才算成功 , 一條失敗則轉(zhuǎn)賬失敗 。 決不允許一部分成功一部分失敗的情況關系型數(shù)據(jù)庫可以事務操作保證事務的特性。
二、 管理事務
數(shù)據(jù)庫默認就有事務 , mysql中默認一條語句獨占一個事務也可以通過手動控制事務:
sql控制事務
start transaction; #開啟一個事務, 這條語句后面的所有sql都將處在同一個事務當中 。這些sql都不會立即起作用 — 沒有改變真正改變數(shù)據(jù)庫中數(shù)據(jù)的操作 。commit;# 提交事務 , 這個事務中的所有sql對數(shù)據(jù)庫的影響立即發(fā)生 , 真正改變數(shù)據(jù)庫的數(shù)據(jù) 。 未提交之前 , 在表面上發(fā)生改變事務內(nèi)部的數(shù)據(jù) , 但是實際上并沒有對數(shù)據(jù)庫的數(shù)據(jù)產(chǎn)生影響。roilback;# 回滾事務,撤銷這個事務中的所有的操作可能對數(shù)據(jù)庫 產(chǎn)生的影響。JDBC中控制事務
conn.setAutoCommit(false);//關閉jdbc自動提交 ,開啟jdbc的事務功能 , 接下來在這個連接執(zhí)行的所有sql都將處在同一個事務中 conn.commit() //提交事務 , 將這個連接上執(zhí)行的事務提交 , 對數(shù)據(jù)庫產(chǎn)生影響conn.roliback() //回滾事務 , 取消這個連接上的執(zhí)行的事務SavePoint sp = conn.setSavePonit(); //設置回滾點 , 相當于游戲中的存檔conn.roliback(sp);//回滾到回滾點 , 注意:回滾到回滾點時 , 回滾點之前的代碼仍然是未提交的狀態(tài) , 如果希望對數(shù)據(jù)庫產(chǎn)生影響仍然需要進行提交操作
三、事務的四大特性 — ACID
原子性 : 事務中的一組操作是不可分割的一個整體 , 要么一起成功 , 要么一起失敗一致性 : 事務前后無論事務是否成功 , 數(shù)據(jù)庫都應該保持一個完整性的狀態(tài)
數(shù)據(jù)庫中數(shù)據(jù)的完整性 : 數(shù)據(jù)庫中數(shù)據(jù)是業(yè)務完整的(符合業(yè)務邏輯)且是約束完整的(符合數(shù)據(jù)庫中所定義的所有約束)。隔離性 : 多個事務之間應該互相隔離 , 互不影響 。 持久性 : 一個事務一旦完成 , 對數(shù)據(jù)庫的影響是永久性的 , 無論發(fā)生什么情況 , 這種影響都不會被取消 。
四、隔離性的問題:
方案一 : 加鎖 – 保證同一時間內(nèi)只能有一個操作數(shù)據(jù) – 完美的保證隔離性 – 但是這樣一來數(shù)據(jù)庫就相當于單線程的狀態(tài)下 , 同一時間只能有一個人操作數(shù)據(jù)庫 , 效率犧牲過大 。 方案二 : 現(xiàn)實生活中 , 并不是所有場景下都需要 那么嚴格的隔離 , 在不同的業(yè)務場景下 , 對隔離的要求是不同的 , 數(shù)據(jù)庫的設計者并沒有將隔離性寫死 , 而是提供了不同的選項 , 數(shù)據(jù)庫使用者根據(jù)自身需求選擇對應的選項 , 選擇相應的隔離能力和數(shù)據(jù)庫的性能 。 通過這些選項 , 數(shù)據(jù)庫 的使用者可以在數(shù)據(jù)庫的性能和隔離性之間做一個權衡
五、四大隔離級別
Read uncommitted – 讀未提交
數(shù)據(jù)庫不保證任何的事務特性 , 可能出現(xiàn)臟讀、不可重復讀、幻讀的問題。隔離性最低 ,但是性能最高臟讀: 一個事務讀取到了另一個事務未提交的數(shù)據(jù)。Read committed – 讀已提交
保證部分的隔離 , 可以防止臟讀問題 ,但是具有不可重復讀 和 幻讀的問題 。 不可重復讀:一個事務讀取到另一個事務已經(jīng)提交的數(shù)據(jù)Repeatable read – 可重復讀
保證了部分的隔離 , 可以防止臟讀、不可重復讀的問題 , 但是具有幻讀的問題幻讀: 一個事務讀取全表數(shù)據(jù)時, 讀取到另一個事務向表中新增或刪除操作提交后的數(shù)據(jù)。
幻讀問題有可能出現(xiàn) , 有可能不出現(xiàn) , 概率很低。 是由于快照造成的Serializable – 可序列化
保證了完全隔離 , 可以防止臟讀 , 不可重復讀 , 幻讀的問題 , 本質(zhì)上是 通過鎖實現(xiàn)的 。 從安全性來說:serializable >Repeatale read > Read committed > Read uncommittes從效率來說:serializable
六、隔離級別的操作
查看數(shù)據(jù)庫隔離級別:
select @@tx_isolation;
設置數(shù)據(jù)庫隔離級別
set [session/globle] transaction isolation level ****;
session表示只設置當前 客戶端的隔離級別 , 立即生效 ; globle表示設置數(shù)據(jù)庫的默認隔離級別 , 但是不會立即生效 , 需要從啟客戶端
七、數(shù)據(jù)庫中的鎖機制
數(shù)據(jù)庫中是有鎖的 , 但是鎖如果設計不好對效率的影響非常大 , 所以數(shù)據(jù)庫的設計者對鎖做了詳細的設計
兩個查詢 — 沒有必要排斥兩個修改 — 必須要排斥一個查詢 , 一個修改 — 根據(jù)具體場景加鎖 , serializable級別 下需要排斥 , 其他隔離級別下不需要 共享鎖
共享鎖和共享鎖可以共存 , 共享鎖和排它鎖不能共存在非serializable級別中查詢不加任何鎖 , 在serializable級別中查詢加共享鎖排它鎖
排它鎖和任何鎖不能共存在任意隔離級別下增刪改都加排它鎖案例:
非serializable級別下操作非serializable級別下操作結果
| 查詢 不加任何鎖 | 查詢 不加任何鎖 | 共存 |
| 增刪改 排它鎖 | 查詢 不加任何鎖 | 共存 |
| 增刪改 排它鎖 | 增刪改 排它鎖 | 排他 |
serializable非serializable結果
| 查詢 共享鎖 | 查詢 不加任何鎖 | 共存 |
| 增刪改 排它鎖 | 查詢 不加任何鎖 | 共存 |
| 增刪改 排它鎖 | 增刪改 排它鎖 | 排他 |
serializableserializable結果
| 查詢 共享鎖 | 查詢 共享鎖 | 共存 |
| 查詢 共享鎖 | 增刪改 排它鎖 | 排他 |
| 增刪改 排他鎖 | 增刪改 排它鎖 | 排他 |
死鎖
當兩邊都是serializable隔離級別時, 兩邊都先進行查詢,這時兩邊都是共享鎖, 再嘗試修改 企圖將共享鎖升級為排它鎖, 則造成了死鎖的現(xiàn)象, 互相等待對方釋放共享鎖 , 都無法執(zhí)行 , 造成死鎖。兩種解決辦法:
提前避免死鎖的發(fā)生mysql沒有避免死鎖 , 嘗試檢測死鎖 ,發(fā)現(xiàn)死鎖的時候 ,錯誤推出一方 , 執(zhí)行另一方的方式解決了死鎖。
總結
以上是生活随笔為你收集整理的大数据WEB阶段(十八)数据库事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。