事務的四大特性
事務的四大特性是事務本身具有的特點。簡稱ACID。
原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麽都發生,要麽都不發生。
一致性(Consistency)
事務前後數據的完整性必須保持一致。
持久性(Durability)
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響。
隔離性(Isolation)
事務的隔離性是指多個用戶並發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個並發事務之間數據要相互隔離。
由於事務的前三大特性數據庫可以幫我們保證。需要討論隔離性;
隔離性(Isolation)
我們知道數據庫的隔離性問題本質上就是多線程並發安全性問題。
可以用鎖來解決多線成並發安全問題,但是如果用了鎖,必然會造成程序的性能大大的下降.對於數據庫這種高並發要求的程序來說這是不可接受的.
我們可以具體分析下隔離性產生的細節:
如果兩個線程並發修改,必然產生多線程並發安全問題,必須隔離開
如果兩個線程並發查詢,必然沒有問題,不需要隔離
如果一個線程修改,一個線程查詢,在不同的應用場景下有可能有問題,有可能沒問題。
隔離性可能造成的問題:
1.臟讀:
一個事務讀取到另一個事務未提交的數據
2.不可重復讀:
一個事務多次讀取數據庫中的同一條記錄,多次查詢的結果不同(一個事務讀取到另一個事務已經提交的數據)
3.虛讀(幻讀)
有可能出現,有可能不出現:
一個事務多次查詢整表數據,多次查詢時,由於有其他事務增刪數據, 造成的查詢結果不同(一個事務讀取到另一個事務已經提交的數據)
數據庫的隔離級別:
1.查詢數據庫的隔離級別:select @@tx_isolation;
2.修改數據庫的隔離級別:
set [session/global] transaction isolation level xxxxxx;
set global transaction isolation level serializable;
不寫默認就是session,修改的是當前客戶端和服務器交互時是使用的隔離級別,並不會影響其他客戶端的隔離級別
如果寫成global,修改的是數據庫默認的隔離級別(即新開客戶端時,默認的隔離級別),並不會修改當前客戶端和已經開啟的客戶端的隔離級別
數據庫中的鎖:
1. 共享鎖
共享鎖和共享鎖可以共存,共享鎖和排他鎖不能共存.在非Serializable隔離級別下做查詢不加任何鎖,在Serializable隔離級別下做查詢加共享鎖.
案例演示:打開兩個mysql客戶端,將隔離級別都設置為Serializable級別,
set session transaction isolation level Serializable;--設置後查詢加了共享鎖
分別在兩個客戶端中查詢:
start transaction;
select * from account;--都能查詢出數據,說明共享鎖可以共存。
2. 排他鎖
排他鎖和共享鎖不能共存,排他鎖和排他鎖也不能共存,在任何隔離級別下做增刪改都加排他鎖.
3.可能的死鎖
mysql可以自動檢測到死鎖,錯誤退出一方執行另一方
更新丟失問題:
1. 更新丟失問題的產生
兩個並發的事務基於同一個查詢結果進行修改,後提交的事務忽略了先提交的事務對數據庫的影響,造成了先提交的事務對數據庫的影響丟失,這個過程就叫做更新丟失
2.更新丟失解決方案:
將數據庫設置為Serializable隔離級別,但是我們一般不會將數據庫設置為Serializable。那麽在非Serializable下又如何解決更新丟失?可以使用樂觀鎖、悲觀鎖。
樂觀鎖和悲觀鎖並不是數據庫中真實存在的鎖,而是兩種解決方案的名字。
(1)悲觀鎖:
在查詢時,手動的加排他鎖,從而在查詢時就排除可能的更新丟失。
select * from users for update;
(2)樂觀鎖:
在表中設計添加一個版本字段,在進行修改時,要求根據具體版本進行修改,
並將版本字段+1,如果更新失敗,說明更新丟失,需要重新進行更新。
兩種解決方案各有優缺點,如果查詢多修改少,用樂觀鎖.
如果修改多於查詢,用悲觀鎖。
事務的四大特性