MySQL基礎關鍵_012_事務

目? 錄

一、概述

二、ACID 四大特性

三、MySQL 事務

?四、事務隔離級別

1.說明

2.現象

(1)臟讀

(2)不可重復讀

(3)幻讀

3.查看隔離級別

4.設置隔離級別

5.隔離級別

(1)初始化

(2)讀未提交

(3)讀提交

(4)可重復讀

(5)串行化

6.可重復讀的幻讀

(1)說明

(2)快照讀解決幻讀

(3)當前讀解決幻讀

(4)出現幻讀的兩種情況


一、概述

  1. 事務是一個最小的工作單元。數據庫中,事務表示一個完整的行為;
  2. 事務只針對 DML 語句
  3. 使用事務機制后,在同一個事務當中,多條 DML 語句或同時執行成功,或同時執行失敗;
  4. 事務的經典實例:賬戶轉賬,或一方金額減少和一方金額增加同時成功,或同時失敗。

二、ACID 四大特性

  1. 原子性(Atomicity):事務包含的所有操作或全部成功,或全部失敗;
  2. 一致性(Consistency):事務開始前和完成后,數據應該是一致的;
  3. 隔離性(Isolation):多個用戶并發訪問數據庫時,數據庫為每一個用戶開啟的事務不能被其他事務的操作所干擾,多個并發事務之間要相互隔離;
  4. 持久性(Durability):一個事務一旦被提交,則對數據庫中的數據改變是永久的,即便是數據庫系統出現故障也不會丟失提交事務的操作。

三、MySQL 事務

  1. 開啟 MySQL 事務:【start transaction;】或【begin;】;
  2. 回滾事務:【rollback;】;
  3. 提交事務:【commit;】;
  4. 只要執行 rollback 或 commit,事務都會結束;
  5. MySQL 默認事務自動提交,執行一條 DML 語句提交一次。

?四、事務隔離級別

1.說明

隔離級別現? 象
臟讀不可重復讀幻讀

讀未提交

(read uncommitted)

存在存在存在

讀提交

(read committed)

不存在存在存在

可重復讀

(repeatable read)

不存在不存在存在

串行化

(serializable)

不存在不存在不存在
  1. 隔離級別排序:讀未提交 < 讀提交 < 可重復讀 < 串行化
  2. 不同隔離級別會存在不同現象,按照嚴重性排序:臟讀 > 不可重復讀 > 幻讀
  3. Oracle 默認隔離級別是讀提交,MySQL 默認隔離級別是可重復讀。

2.現象

(1)臟讀

? ? ? ? 一個事務讀取了另一個事務尚未提交的數據。此時如果另一個事務回滾或修改了數據,那么讀取臟數據的事務就會出現數據處理錯誤。


(2)不可重復讀

????????一個事務內,多次讀取同一條數據,得到的結果可能不一致。因為其他事務可能對該數據做出修改操作。


(3)幻讀

????????事務執行過程中,前后幾次相同查詢條件得到的結果集不一致,可能更多也可能更少。


3.查看隔離級別

  1. 查看當前會話的隔離級別:【select @@transaction_isolation;】;
  2. 查看全局的隔離級別:【select @@global.transaction_isolation;】。
select @@global.transaction_isolation;select @@transaction_isolation;


4.設置隔離級別

  1. 設置當前會話的隔離級別:【set session transaction isolation level <隔離級別>】;
  2. 設置全局的隔離級別:【set global transaction isolation level <隔離級別>】。
# 設置全局隔離級別-- 讀未提交
set global transaction isolation leve read uncommitted;-- 讀提交
set global transaction isolation level read committed;-- 可重復讀
set global transaction isolation level repeatable read;-- 串行化
set global transaction isolation level serializable;# 設置會話隔離級別-- 讀未提交
set session transaction isolation leve read uncommitted;-- 讀提交
set session transaction isolation level read committed;-- 可重復讀
set session transaction isolation level repeatable read;-- 串行化
set session transaction isolation level serializable;


5.隔離級別

(1)初始化

? ? ? ? 事先準備好一個 users 表,表中有 id,name,gender 字段。

drop table if exists users;create table users(id int primary key auto_increment,name varchar(10),gender varchar(2) default '未知'
);insert into users(name, gender) values('黃梓婷', '女'),('趙聰', '男'),('呂不韋', '男');select * from users;


(2)讀未提交

  1. A 事務與 B 事務,A 事務可以讀到 B 事務未提交的數據
  2. 這種級別的兩個事務之間幾乎沒有隔離,實際數據庫產品中,沒有默認該隔離級別的;
  3. 但前隔離級別,臟讀、不可重復讀、幻讀 現象都存在
  4. 模擬實例:先將全局事務隔離級別設置為 read uncommitted。然后開啟兩個 dos 命令窗口分別登錄 MySQL 來模擬 A、B事務。
-- 1.設置全局隔離級別
set global transaction isolation level read uncommitted;-- 2.然后打開兩個 dos 命令窗口,分別登錄 MySQL
A 事務B 事務
3. mysql> use test;
4. mysql> use test;
5. mysql> start transaction;
6. mysql> start transaction;
7. mysql> select * from users;
8.?mysql> insert into users(name, gender) values('陳子悅', '女');
9.?mysql> select * from users;

? ? ? ? ?可以看到,出現了臟讀,意味著三個現象都會出現。


(3)讀提交

  1. A 事務與 B 事務,A 事務可以讀取到 B 事務提交之后的數據
  2. Oracle 默認是此隔離級別;
  3. 當前隔離級別,會出現不可重復讀和幻讀現象
  4. 模擬實例:先將全局事務隔離級別設置為 read committed。然后開啟兩個 dos 命令窗口分別登錄 MySQL 來模擬 A、B事務。
-- 1.設置全局隔離級別
set global transaction isolation level read committed;-- 2.然后打開兩個 dos 命令窗口,分別登錄 MySQL
A 事務B 事務
3. mysql> use test;
4. mysql> use test;
5. mysql> start transaction;
6. mysql> start transaction;
7. mysql> select * from users;
8.?mysql> insert into users(name, gender) values('陳子悅', '女');
9.?mysql> select * from users;
9.?mysql> commit;
10.?mysql> select * from users;
11.?mysql> update users set name = '牛佳佳' where id = 2;
12.?mysql> select * from users;

? ? ? ? 可以看到,出現了不可重復讀和幻讀。?


(4)可重復讀

  1. A 事務與 B 事務,A 事務開啟后讀取記錄,B 事務修改數據并提交,A 事務讀取到的還是修改前的記錄;
  2. MySQL 默認是此隔離級別;
  3. 模擬實例:先將全局事務隔離級別設置為 repeatable read。然后開啟兩個 dos 命令窗口分別登錄 MySQL 來模擬 A、B事務。
-- 1.設置全局隔離級別
set global transaction isolation level repeatable read;-- 2.然后打開兩個 dos 命令窗口,分別登錄 MySQL
A 事務B 事務
3. mysql> use test;
4. mysql> use test;
5. mysql> start transaction;
6. mysql> start transaction;
7. mysql> select * from users;
8.?mysql> update users set name = '艾東東' where id = 2;
9.?mysql> select * from users;
10.?mysql> commit;
11.?mysql> select * from users;
12.?mysql> insert into users(name, gender) values('張弘毅', '男');
13.?mysql> commit;
14.?mysql> select * from users;
15.?select * from users for update;

# A 事務
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)mysql> select * from users;
+----+--------+--------+
| id | name   | gender |
+----+--------+--------+
|  1 | 黃梓婷 | 女     |
|  2 | 牛佳佳 | 男     |
|  3 | 呂不韋 | 男     |
|  5 | 陳子悅 | 女     |
+----+--------+--------+
4 rows in set (0.00 sec)mysql> select * from users;
+----+--------+--------+
| id | name   | gender |
+----+--------+--------+
|  1 | 黃梓婷 | 女     |
|  2 | 牛佳佳 | 男     |
|  3 | 呂不韋 | 男     |
|  5 | 陳子悅 | 女     |
+----+--------+--------+
4 rows in set (0.00 sec)mysql> select * from users;
+----+--------+--------+
| id | name   | gender |
+----+--------+--------+
|  1 | 黃梓婷 | 女     |
|  2 | 牛佳佳 | 男     |
|  3 | 呂不韋 | 男     |
|  5 | 陳子悅 | 女     |
+----+--------+--------+
4 rows in set (0.00 sec)mysql> select * from users;
+----+--------+--------+
| id | name   | gender |
+----+--------+--------+
|  1 | 黃梓婷 | 女     |
|  2 | 牛佳佳 | 男     |
|  3 | 呂不韋 | 男     |
|  5 | 陳子悅 | 女     |
+----+--------+--------+
4 rows in set (0.00 sec)mysql> select * from users for update;
+----+--------+--------+
| id | name   | gender |
+----+--------+--------+
|  1 | 黃梓婷 | 女     |
|  2 | 艾東東 | 男     |
|  3 | 呂不韋 | 男     |
|  5 | 陳子悅 | 女     |
|  6 | 張弘毅 | 男     |
+----+--------+--------+
5 rows in set (0.00 sec)
# B 事務
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)mysql> update users set name = '艾東東' where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> commit;
Query OK, 0 rows affected (0.00 sec)mysql> insert into users(name, gender) values('張弘毅', '男');
Query OK, 1 row affected (0.02 sec)mysql> commit;
Query OK, 0 rows affected (0.00 sec)

? ? ? ? 可以看到 A 事務在使用【select * from users for update;】語句查詢時會出現幻讀,但是不加【for update】不會出現幻讀。也就是說,幻讀是可能會出現的,for update 是當前讀。


(5)串行化

  1. 此隔離級別,避免了所有的問題
  2. 但是效率低,因為這種隔離級別會導致事務排隊處理,不支持并發;
  3. 模擬實例:先將全局事務隔離級別設置為 serializable。然后開啟兩個 dos 命令窗口分別登錄 MySQL 來模擬 A、B事務。
-- 1.設置全局隔離級別
set global transaction isolation level serializable;-- 2.然后打開兩個 dos 命令窗口,分別登錄 MySQL
A 事務B 事務
3. mysql> use test;
4. mysql> use test;
5. mysql> start transaction;
6. mysql> start transaction;
7. mysql> select * from users;
8.?mysql> insert into users(name, gender) values('周子恩', '女');
9. commit;

? ? ? ? 在 B 事務執行完 insert 語句后,會等待 A 事務結束,否則 B 事務不會進入下一步。兩個事務是串行執行的。?


6.可重復讀的幻讀

(1)說明

  1. MySQL 默認隔離級別是可重復讀,但是不可以完全避免幻讀問題;
  2. 解決幻讀的方法:
    1. 快照讀:普通 select 語句都是快照讀。通過 MVCC(多版本并發控制) 方式解決幻讀,因為在可重復的隔離級別中,事務執行的查詢數據與該事務啟動時查詢的數據是一致的,即使中間有新插入的數據,也不會被查詢出來,所以避免了幻讀問題;
    2. 當前讀:帶有 for update 的 select 語句、insert 語句、alert 語句、delete 語句都是當前讀。通過 next-key lock(記錄鎖 + 間隙鎖)的方式解決幻讀,因為執行 select …… for update 語句時,會加上 next-key lock。若其他事務在 next-key lock 鎖范圍內插入了一條記錄,則該語句會被阻塞,無法成功插入,所以也避免了幻讀問題。

(2)快照讀解決幻讀

  1. 在整個事務處理過程中,執行相同的普通 select 語句,都是讀取快照;
  2. 快照是固定某個時刻的數據;
  3. 原理:底層由 MVCC 實現,開始事務后,執行第一個查詢語句后,會創建一個 read view,后續的查詢語句利用該 read view,通過該 read view 可以在 undo log 版本鏈中找到事務開始時的數據,所以事務過程中每次查詢到的數據是一致的。

(3)當前讀解決幻讀

  1. 每一次都讀取最新數據;
  2. 事務開始,會對查詢范圍內的數據加鎖,不允許其他事務對該范圍內的數據進行增、刪、改。即該 select 語句范圍內的數據不允許并發,只能排隊執行。next-key lock,就是 間隙鎖 + 記錄鎖,間隙鎖用來保證鎖定范圍內不允許執行 insert 操作,記錄鎖保證鎖定范圍不允許執行 update 和 delete 操作。

(4)出現幻讀的兩種情況

  1. ?A 事務與 B 事務,在 A 事務中第一次查詢使用快照讀B 事務插入數據。然后在 A 事務中第二次查詢使用當前讀,則會產生幻讀現象;

  2. A 事務與 B 事務,在 A 事務中第一次查詢使用快照讀,在 B 事務中插入數據。然后在 A 事務中更新 B 事務插入的那條記錄。最后在 A 事務中再次使用快照讀,則會產生幻讀現象。(因為執行 update 操作,會在底層執行一次當前讀)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/80011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/80011.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/80011.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Hutool中的Pair類詳解

1. Pair類概述 Hutool工具庫中的Pair類是一個簡單的鍵值對數據結構&#xff0c;用于存儲兩個相關聯的對象。它類似于Map的Entry&#xff0c;但更加輕量級&#xff0c;適用于需要臨時存儲兩個相關聯數據的場景。 2. Pair類的主要特點 簡單輕量&#xff1a;不依賴復雜的數據結…

02-GBase 8s 事務型數據庫 客戶端工具dbaccess

dbaccess概述 數據庫產品通常會提供一個命令行客戶端工具。 數據庫廠商 命令行客戶端 Oracle sqlplus MySQL mysql Marladb mysql GBase 8s dbaccess Kingbase ES ksql DM8 disql dbaccess 是 GBase 8s 數…

手撕基于AMQP協議的簡易消息隊列-8(單元測試的編寫)

在MQTest中編寫模塊的單元測試 在MQTest中編寫makefile文件來編譯客戶端模塊 all:Test_FileHelper Test_Exchange Test_Queue Test_Binding Test_Message Test_VirtualHost Test_Route Test_Consumer Test_Channel Test_Connection Test_VirtualHost:Test_VirtualHost.cpp ..…

Spark 之 metrics

peak memory.//sql/core/src/main/scala/org/apache/spark/sql/execution/aggregate/HashAggregateExec.scala: “peakMemory” -> SQLMetrics.createSizeMetric(sparkContext, “peak memory”), .//sql/core/src/main/scala/org/apache/spark/sql/execution/SortExec.scal…

HTTP/HTTPS協議(請求響應模型、狀態碼)

目錄 HTTP/HTTPS協議簡介 HTTP協議 HTTPS協議 請求 - 響應模型 HTTP請求 &#xff08;二&#xff09;HTTP響應 HTTPS協議與HTTP協議在請求 - 響應模型中的區別 HTTP/HTTPS協議簡介 HTTP協議 定義 HTTP&#xff08;HyperText Transfer Protocol&#xff09;即超文本傳輸…

OpenHarmony 5.0 切換已連接過的wifi切換失敗

目錄 1.背景 2.流程分析 3.方案 1.背景 在OpenHarmony 5.0的設置中,輸入密碼進行wifi連接可以正常連接,然后多個已經連接過的wifi進行切換發現大概率切換失敗 2.流程分析 wifi連接過程其實是先進行斷開當前的wifi連接,然后再連接另一個wifi,如下: 雖然上述流程看起來沒…

【Ollama】docker離線部署Ollama+deepseek

因為要做項目&#xff0c;實驗室的服務器不聯網&#xff0c;所以只能先打包一個基礎的docker環境&#xff0c;然后再在實驗室的服務器上進行解壓和配置環境 參考&#xff1a;https://zhuanlan.zhihu.com/p/23377266873 1.打包基礎的docker環境 這里最好用有cuda的&#xff0c…

如何使用極狐GitLab 軟件包倉庫功能托管 terraform?

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 Terraform 模塊庫 (BASIC ALL) 基礎設施倉庫和 Terraform 模塊倉庫合并到單個 Terraform 模塊倉庫功能引入于極狐GitLab 15.1…

【QT】深入理解 Qt 中的對象樹:機制、用途與最佳實踐

深入理解 Qt 中的對象樹&#xff1a;機制、用途與最佳實踐 在使用 Qt 編程時&#xff0c;你是否注意到很多對象可以設置“父對象”&#xff1f;比如&#xff1a; QPushButton* btn new QPushButton(parentWidget);這不是簡單的層級結構&#xff0c;而是 Qt 強大而優雅的 對象…

比較入站和出站防火墻規則

組織需要仔細配置防火墻規則&#xff0c;監控網絡的傳入和傳出流量&#xff0c;從而最大限度降低遭受攻擊的風險。在有效管理入站和出站防火墻規則前&#xff0c;了解入站與出站流量的區別至關重要。 一、什么是入站流量&#xff1f; 入站流量指的是并非源自網絡內部&#xf…

Unity-Shader詳解-其五

關于Unity的Shader部分的基礎知識其實已經講解得差不多了&#xff0c;今天我們來一些實例分享&#xff1a; 溶解 效果如下&#xff1a; 代碼如下&#xff1a; Shader "Chapter8/chapter8_1" {Properties{// 定義屬性[NoScaleOffset]_Albedo("Albedo", 2…

COLT_CMDB_linux_userInfo_20250508.sh修復歷史腳本輸出指標信息中userName與輸出信息不一致問題

#!/bin/bash #IT_BEGIN #IT_TYPE3 #IT SYSTEM_LINUX_AGENTUSERDISCOVER|discovery.user[disc] #原型指標 #IT_RULE SYSTEM_LINUX_AGENTUSERGROUPID|groupId[{#USERNAME}] #IT_RULE SYSTEM_LINUX_AGENTUSERHOME|userHome[{#USERNAME}] #IT_RULE SYSTEM_LINUX_AGENTUSERNAME|user…

TCP 與 UDP報文

** TCP 與 UDP報文** 1. 引言 在網絡通信中&#xff0c;TCP&#xff08;傳輸控制協議&#xff09; 和 UDP&#xff08;用戶數據報協議&#xff09; 是兩種最核心的傳輸層協議。它們各自適用于不同的場景&#xff0c;理解其工作原理對開發高性能網絡應用至關重要。本文將詳細解…

LabVIEW燃氣輪機測控系統

在能源需求不斷增長以及生態環境保護備受重視的背景下&#xff0c;微型燃氣輪機憑借其在經濟性、可靠性、維護性及排放性等方面的顯著優勢&#xff0c;在航空航天、分布式發電等眾多領域得到廣泛應用。隨著計算機技術的快速發展&#xff0c;虛擬儀器應運而生&#xff0c;LabVIE…

基于vueflow可拖拽元素的示例(基于官網示例的單文件示例)

效果圖 代碼 <template><div style"width: 100%;height: calc(100vh - 84px)"><VueFlow :nodes"nodes" :edges"edges" drop"onDrop" dragover"onDragOver" dragleave"onDragLeave"><div cl…

筆試專題(十六)

文章目錄 相差不超過k的最多數題解代碼 最長公共子序列&#xff08;一&#xff09;題解代碼 小紅的口罩題解代碼 春游題解代碼 相差不超過k的最多數 題目鏈接 題解 1. 排序 滑動窗口 2. 為什么使用滑動窗口&#xff1f; 因為max-min < k&#xff0c;求這個區間內的數最…

技術視界 | 青龍機器人訓練地形詳解(三):復雜地形精講之臺階

在前兩篇中&#xff0c;我們依次講解了“如何創建一個地形”以及“如何將地形添加到訓練環境中”。從基礎出發&#xff0c;逐步構建機器人可交互的三維仿真環境。在機器人強化學習訓練中&#xff0c;地形的復雜度決定了策略的泛化能力&#xff0c;僅靠 jump_plat 和 jump_pit 等…

MYSQL之索引結構,為何要用B+樹

索引的目的就是為了提高查詢效率 索引的結構是B樹&#xff0c;那么說到B樹&#xff0c;必須提一下其他三種結構&#xff0c;分別是&#xff1a;二叉查找樹、平衡二叉樹、B樹 我們來看看各自的結構特征 二叉查找樹 特點:任何節點的左子節點的值都小于當前節點的值&#xff0c;右…

3.2.3 掌握RDD轉換算子 - 2. 過濾算子 - filter()

在本節課中&#xff0c;我們深入學習了Spark RDD的過濾算子filter()。filter()算子能夠通過指定的函數對RDD中的元素進行篩選&#xff0c;返回一個滿足條件的新RDD&#xff0c;通常新RDD的元素個數會比源RDD少。通過案例演示&#xff0c;我們掌握了如何使用filter()來過濾列表中…

vue3使用輪播圖組件swiper

一、在swiper的官網源碼下載地址 下載Swiper - Swiper中文網 二、官網瀏覽輪播圖類型地址 Swiper演示 - Swiper中文網 三、swiper配置參數地址 中文api - Swiper中文網 四、在vue3項目引入swiper npm install swiper 五、在vue3中使用 官網vue3中使用&#xff1a;Swiper…