資料庫隔離級別

来源:https://www.cnblogs.com/moyuduo/archive/2020/04/05/12639482.html
-Advertisement-
Play Games

資料庫隔離級別 如果沒有隔離級別會出現的問題 臟讀 意思是讀取到了事務正在修改的數據,如果事務回滾,那麼拿到的數據就是錯誤的 | 時間 | 事務A | 事務B | | | | | | 1 | 開始事務 | | | 2 | 讀取quantity為5 | | | 3 | 修改quantity為4 | | ...


資料庫隔離級別

如果沒有隔離級別會出現的問題

臟讀

意思是讀取到了事務正在修改的數據,如果事務回滾,那麼拿到的數據就是錯誤的

時間 事務A 事務B
1 開始事務
2 讀取quantity為5
3 修改quantity為4
4 開始事務
5 讀取到quantity為4
6 發生錯誤,回滾,quantity為5
7 提交事務

在按照正常邏輯quantity應該為5

不可重覆讀

時間 事務A 事務B
1 開始事務
2 讀取quantity為5
3 開始事務
4 修改quantity為4
5 提交事務
6 讀取quantity為4
7 提交事務

在同一個事務內,兩次讀取同一個數據產生不一致

幻讀

時間 事務A 事務B
1 開始事務
2 更新所有行的quantity為100
3 開始事務
4 插入一行quantity為5
5 提交事務
6 查詢所有行的quantity
7 提交事務

當一個事務內更新所有行後,另一個事務插入了新行,當再次查看記錄時,發現有未更新的記錄,好像幻覺一樣

丟失更新

第一種情況:

時間 事務A 事務B
1 開始事務
2 查詢到quantity為10
3 開始事務
4 查詢到quantity為10
5 更新quantity為11
6 提交事務
7 更新quantity為9
8 事務回滾,quantity為10

可以看到,回滾的事務把正常事務的數據覆蓋了,正常事務的數據丟失了

第二種情況:

時間 事務A 事務B
1 開始事務
2 查詢到quantity為10
3 開始事務
4 查詢到quantity為10
5 更新quantity為9
6 提交事務
7 更新quantity為11
8 提交事務

這種情況是事務在執行期間,其他事務對數據進行了修改,那麼當前事務拿到的數據就是錯的,對錯的數據進行更新,那也就沒有意義了

解決方法

對於臟讀、不可重覆讀、幻讀

我們可以使用資料庫提供的隔離級別來避免以上情況

隔離級別 臟讀 不可重覆讀 幻讀
Read-Uncommitted(讀取未提交的內容)
Read-Committed(讀取已提交的內容) ×
Repeatable-Read(可重讀) × ×
Serializable(串列化) × × ×

Mysql的預設隔離級別為Repeatable-Read,可以通過以下命令查看

SELECT @@global.tx_isolation;--查看全局隔離級別
SELECT @@session.tx_isolation;--查看當前連接的隔離級別

修改隔離級別

SET @@global.tx_isolation='Read-Committed'
SET @@session.tx_isolation='Read-Committed'
--或
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE

對於丟失更新

使用悲觀鎖

悲觀鎖主要有共用鎖(讀鎖)和排他鎖(寫鎖)

  • 共用鎖是指多個事務可以共用一個一把鎖,都可以讀取到數據,但是不能修改
  • 排他鎖就是一個事務獲得了排他鎖,那麼其他事務就不能獲得鎖(包括共用鎖和排他鎖),獲取排他鎖的事務可以對數據進行訪問和修改

Mysql預設開啟了自動事務提交,可以使用以下命令關閉

SET autocommit=0	--關閉自動事務提交

這裡必須要強調一下鎖的概念,不管是共用鎖還是排他鎖,都是我們給每一個數據元素加的,如果一個數據元素已經有了排他鎖,那麼久不能再給它加任何鎖,如果一個數據元素有共用鎖,那麼還可以給它加共用鎖,Mysql的InnoDB引擎預設給insert、update、delete都加了排他鎖,而select未加任何鎖

新建一個查詢視窗,開始事務,但是沒有提交,因為update預設給數據元素加排他鎖,所以這個時候我們去更新該數據元素就會出現

上一個事務還沒有提交,數據元素還有排他鎖,這個update語句要給數據元素加排他鎖,所以只有等待,這也驗證了update語句預設會給相關的數據元素加排他鎖

如果使用select語句加共用鎖進行查詢一樣會阻塞

但是使用select語句不加任何鎖是可以查出數據的,但是數據是更新之前的

所以,使用悲觀鎖在高併發情況下,對於減庫存這樣的操作,首先要使用排他鎖的select語句拿到庫存,如果已經有事務對這個數據元素上了鎖,那麼只有等待該事務釋放鎖,只有這樣拿到的庫存才是正確的

BEGIN;
DECLARE @now_quantity INT;
SELECT quantity INTO @now_quantity FROM item WHERE id=1 FOR UPDATE;//一定要加排他鎖
UPDATE item SET quantity=@now_quantity-1 WHERE id=1;
COMMIT;

而且需要註意,MySQL InnoDB預設行級鎖。行級鎖都是基於索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住

使用悲觀鎖的方式解決丟失更新很簡單,但是也會帶來效率上的問題,如果一個事務上了鎖,那麼其他的都只有等待

使用樂觀鎖

我們可以給表中加上一個version自增的版本欄位,查詢的時候拿到版本欄位和庫存,當需要去更新的時候,如果版本不一致,那麼需要重新查詢,重覆上述步驟,知道拿到的版本和資料庫中的版本一致時,才進行更新,這樣就不需要等待,效率更高



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 顯示目錄和文件的命令 Ls:用於查看所有文件夾的命令。 Dir:用於顯示指定文件夾和目錄的命令 Tree: 以樹狀圖列出目錄內容 Du:顯示目錄或文件大小 查找文件 locate a.txt :在系統全局範圍內查找文件名包含a.txt字樣的文件(比find快) find /home -mtime - ...
  • 本文主要是本人對 unix 操作系統中的數據緩衝區高速緩衝設計以及其演算法思路的一些理解,可能由於水平有限,文中難免會有錯誤,如若發現,懇請支持,謝謝! ...
  • SpringBoot系列(二)入門知識 往期推薦 "SpringBoot系列(一)idea新建springboot項目" 引言 本來新建springboot項目應該放在入門知識這一章的,但是由於新建springboot的第一篇文章只介紹了一種新建項目的方法,所以在這一章講解一下springboot的 ...
  • 因項目需要申請了新伺服器,故要重新配置環境。 nginx安裝: 一鍵安裝四個依賴: yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 進入/usr/local/src目錄,創建nginx文件夾 cd /usr/lo ...
  • 良許在工作中,寫過一個 Shell 腳本,這個腳本可以從 4 個 NTP 伺服器輪流獲取時間,然後將最可靠的時間設置為系統時間。 因為我們對於時間的要求比較高,需要在短時間內就獲取到正確的時間。所以我們就需要對這個腳本運行時間進行測試,看看從開始運行到正確設置時間需要花費多少時間。 其實在工作中,還 ...
  • 1、命令基礎 1.1、命令操作語法 命令 [參數] [文件] 參數,可有可無 文件,可有可無 2、基礎命令 2.1、查看當前工作目錄 pwd print name of current/workin directory 列印 名字 或 工作 目錄 2.2、切換目錄 cd cd 目錄 相對路徑與絕對路 ...
  • [TOC] 1.集群架構 | 主機名 | 角色 | IP地址 | | : : | : : | : : | | hdss7 21.host.com | flannel | 10.4.7.21 | | hdss7 22.host.com | flannel | 10.4.7.22 | 部署方法以hdss ...
  • redis 實戰-redis 事務 1.描述 redis 事務單獨的隔離操作:事務中的所有命令都會序列化、按順序執行。事務在執行過程中,不會被其他客戶端發送過來的命令請求所打斷。 redis 事務沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...