mysql加強(7)~事務、事務併發、解決事務併發的方法
一、事務Transaction(簡寫tx):
在資料庫中,事務是指一組邏輯操作
(不可分割的多個操作---一個事務,從一個狀態變成另外一個狀態。),無論成或敗,都作為一個整體進行工作,要麼全部執行,要麼全部不執行。
■ 引入背景:銀行轉賬突遇斷電的bug
1、事務的ACID屬性:
① 原子性:事務是滿足原子操作單元的,要麼都執行,要麼都不執行。
② 一致性:事務必須使資料庫從一個一致性狀態變成另外一個一致性狀態。事務開始和完成,資料必須保持一致。(資料不被破壞)【'資料守恆'】
③ 隔離性:事務之間有各自的空間,事務之間不被打擾。併發執行的事務之間彼此相互獨立、互相不干擾.
④ 永續性:事務一旦提交後,資料是永久性的、不可回滾。(資料的修改是永久的)
■ 事務只是一個改變,是一些操作的集合,事務本身不具備4個特性,但是我們需要讓事務滿足ACID特性,才能稱它為一個正確的事務。
■ 在開發中,我們可以不使用外來鍵,但是必須要有事務(儲存引擎- innoDB)
■ 處理事務的兩個動作:
-
提交 commit:當整個事務中,所有的邏輯操作都是正常執行成功。 --》提交事務
-
回滾 rollback:當整個事務中,有一個或多個邏輯操作執行失敗。 --》回滾事務,撤銷該事務中所有的操作,恢復到最初的狀態。
2、隔離級別:
-
事務的ACID特性中的隔離性是具有級別的哈,所以才有事務併發出現的各種情況。
-
隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。
-
mysql 是使用可重複讀取(Repeatable Read), 保證了資料的讀取一致性,避免了髒讀、不可重複讀。
- 預設情況,mysql不會出現幻讀[除非 select * from 表名 lock in share mode;]
- mysql中鎖是基於索引機制,也不會出現第一類丟失更新(回滾丟失)
隔離級別 髒讀 不可重複讀 幻讀 oracle---讀已提交(只是避免了髒讀) 否 是 是 mysql---可重複讀取(避免了髒讀和不可重複讀) 否 否 是
■ mysql中的4種隔離級別(重點看是否會出現髒讀、不可重複讀、幻讀即可)
-
■ 這裡最嚴重的就是丟失更新問題
-
讀取未提交:會出現髒讀,還有事務A的資料仍然會因為事務B的insert/update、delete 從而出現幻讀、不可重複讀
-
讀取已提交:未提交的寫操作的事務不允許被其他事務訪問到。避免了髒讀,但是事務A的資料,仍然會因為事務B的insert/update、delete 從而出現幻讀、不可重複讀。
-
可重複讀取:避免了不可重複讀,但是卻有可能出現幻讀。
-
序列化:要求事務一個接著一個進行執行,不可能併發執行。
-
二、事務併發
1、資料庫的事務併發問題:多個事務併發訪問/修改同一個資源
★ 跟java中的執行緒問題---併發問題差不多,都是針對同一資源,同時訪問/修改出現的問題。
■ 事務併發可能導致的問題【例子:兩個客戶端同時對同一個銀行賬號進行操作,一個客戶端進行存取,一個客戶端進行取錢】
(1)第一類丟失更新:撤銷rollback
一個事務時,把其他事務已經提交更新的資料回滾掉了。
(2)第二類丟失更新:提交commit
一個事務時,把其他事務已經提交更新的資料覆蓋掉了。
(3)髒讀:A事務未提交,但是B事務卻讀取到A事務的結果【讀取到了B事務未提交
的結果】(破壞隔離性)
(4)幻讀:A事務在本次事務中,對自己未操作過
的資料(B事務insert
了一些資料),A事務進行兩次讀取,發現第一次讀取時,記錄不存在,第二次讀取,記錄出現了(破壞一致性,insert)
(5)不可重複讀:跟幻讀類似,A事務在本次事務中,對自己未操作過
的資料(B事務update/delete
了一些資料),A事務進行兩次讀取,發現兩次讀取的記錄值不同(破壞一致性,update/delete)
❀ 每一個事務是有自己的空間的概念
-
【第一類丟失更新】
回滾丟失
,把前一個提交的事務的結果回滾到資料庫最初的數 -
【第二類丟失更新】
覆蓋丟失
,通過提交事務,把前一個提交的事務的結果給覆蓋掉 -
髒讀: 事務A讀到事務B未提交的更新資料 (Oracle不會出現髒讀)
-
幻讀:事務A第二次查詢時,讀到了事務B
新增
提交的資料,即事務A兩次查詢時的記錄條數不同,"產生幻覺"。【一般使用表鎖機制,防止新增資料。】 -
不可重複讀:跟幻讀類似(只是幻讀是讀到事務B
新增
資料),事務A第二次查詢時,讀到了事務B修改
提交的資料,即事務A兩次查詢時的結果的值不同不同
三、解決事務併發的方法(悲觀鎖/樂觀鎖)
1、悲觀鎖:事務A在操作時,悲觀地認為其他事務會進來干擾自己。---[用的比較多,非常安全]。
(1)悲觀鎖:使用資料庫自身的排它鎖機制 [★原理:資料庫自身的鎖機制(寫鎖)]
- DML操作會自動加上排它鎖(排斥其他鎖)
- DQL操作需要我們手動加上排它鎖
- select * from 表名
for update
;
- select * from 表名
■ 使用客戶端工具Navicat模擬(開啟兩個命令列視窗,可以拖動出來方便檢視)併發:
-
DML操作會自動加上排它鎖(排斥其他鎖)
-
DQL操作需要我們手動加上排它鎖
■ 查詢事務加上了 for update,其中一個事務處於阻塞狀態,等著另一個事務的提交或回滾。
2、樂觀鎖:事務A在操作時,樂觀地認為其他事務不會進來干擾自己。
(1) ★原理:在表中額外新增一個列,用來表示修改的版本(整型型別),修改一次就把版本增加1
.
- 舉例:事務A併發修改person表中的name欄位。