事務&鎖
事務
事務,由一組 sql 語句組成的執行單元,要麼都執行成功,要麼回滾。事務符合 ACID 原則
ACID 原則
-
Atomicity-原子性:執行單元,要麼執行成功,要麼回滾
-
Consistency-一致性:事務開始和結束之後,數據庫的完整性約束沒有破壞
-
Isolation-隔離性:多個事務併發執行時,彼此之間並不會相互影響
-
Durability-持久性:事務對數據庫所做的更改會持久的保存在數據庫中
事務的隔離性
數據庫中事務的隔離性分爲了 4 個層級
- read uncommitted:未提交讀,會引發 髒讀,不可重複讀,幻讀
- read committed:已提交讀,會引發 不可重複讀,幻讀
- repeatable read:可重複讀,會引發 幻讀
- serializable :序列化
事務的隔離性越高,併發性越低,對業務系統的影響性也就越大。
鎖
悲觀鎖
定義:指對數據被外界修改持悲觀態度,具有獨佔性和排他性。
分類:
- 共享鎖(讀鎖,S 鎖):允許其他進程讀,但不允許修改
- 排他鎖(寫鎖,X 鎖):鎖定期間,不允許其他進程讀寫
實現:依賴於數據庫的鎖機制
實例:
start transaction;
select p.productCount from product p where p.productId = 1 for update;
update product p set p.productCount=p.productCount-1 where p.productId=1 ;
commit;
樂觀鎖
定義:指外界對數據修改持樂觀態度,認爲其他進程不會影響到自己要修改的數據。
實現:使用程序便可實現
- 使用數據版本實現:爲數據增加一個 version,每修改一次數據便使 version 變大,只增不減。
- 使用時間戳實現:天然遞增性
實例:
start transaction;
// version = 1
select p.productCount, p.version from product p where p.productId = 1;
update product p set p.productCount=p.productCount-1, p.version=p.version+1 where p.productId = 1 and version = 1;
commit
// 不在事務中也可實現
// version = 1
select p.productCount, p.version from product p where p.productId = 1;
update product p set p.productCount=p.productCount-1, p.version=p.version+1 where p.productId = 1 and version = 1;
悲觀鎖 VS 樂觀鎖
悲觀鎖:依賴於數據庫鎖,效率低。更新失敗的概率低
樂觀鎖:並未真正加鎖,效率高。但一旦鎖的粒度把握不好,更新失敗的概率較大,容易發生業務失敗。
在現在 3 高的要求下(高併發,高性能,高可用),悲觀鎖用的越來越少。
細化鎖粒度
不要長時間持有不必要的鎖
// 控制了只有 p.count 爲 1 時才採用鎖機制
update product p set p.count=p.count-1 where p.id=1 and p.count-1>0