最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL 事務的概念及ACID屬性和使用詳解

 更新時間:2025年05月29日 11:26:02   作者:IsLand1314~  
MySQL通過多線程實現(xiàn)存儲工作,因此在并發(fā)訪問場景中,事務確保了數據操作的一致性和可靠性,下面通過本文給大家介紹MySQL 事務的概念及ACID屬性和使用詳解,感興趣的朋友一起看看吧

一、什么是事務

  • 定義:由一條或者多條 sql 語句構成的 sql 集合體,這個集合體合在一起共同要完成某種任務。MySQL通過多線程實現(xiàn)存儲工作,因此在并發(fā)訪問場景中,事務確保了數據操作的一致性和可靠性。 事務還規(guī)定 不同的客戶端看到的數據是不相同的
    • 事務就是要做的或所做的事情,主要用于 處理操作量大,復雜度高的數據
    • 假設一種場景:你畢業(yè)了, 學校的教務系統(tǒng)后臺 MySQL 中,不在需要你的數據,要刪除你的所有信息(一般不會:) ), 那么要刪除你的 基本信息(姓名,電話,籍貫等)的同時,也刪除和你有關的其他信息,比如:你的各科成績,你在校表 現(xiàn),甚至你在論壇發(fā)過的文章等。這樣,就需要多條 MySQL 語句構成,那么所有這些操作合起來,就構成了一個事務。
  • 背景:在沒有控制的情況下進行 CURD 操作(創(chuàng)建、更新、讀取、刪除)可能導致數據不一致的問題。例如,在火車票售票系統(tǒng)中,兩個用戶同時嘗試購買最后一張票,可能造成同一張票被賣出兩次的現(xiàn)象

CURD滿足什么屬性,能解決上述問題?

  • 買票的過程得是原子的吧
  • 買票互相應該不能影響吧
  • 買完票應該要永久有效吧
  • 買前,和買后都要是確定的狀態(tài)吧

二、事務的屬性及使用

2.1 事務的 ACID 屬性

一個 MySQL 數據庫,可不止你一個事務在運行,同一時刻,甚至有大量的請求被包裝成 事務,在向 MySQL 服務器發(fā)起事務處理請求。而每條事務至少一條 SQL ,最多很多 SQL ;這樣如果大 家都訪問同樣的表數據,在不加保護的情況,就絕對會出現(xiàn)問題。甚至,因為事務由多條 SQL 構成,那 么,也會存在執(zhí)行到一半出錯或者不想再執(zhí)行的情況,那么已經執(zhí)行的怎么辦呢?

所有,一個完整的事務,絕對不是簡單的 sql 集合,還需要滿足如下四個屬性:

  • 原子性(Atomicity,或稱不可分割性):事務的所有操作要么全部完成,要么完全不執(zhí)行,任何一部分失敗都會導致整個事務的回滾。
  • 一致性(Consistency):事務前后,數據庫應保持一致的狀態(tài),即事務不應破壞數據庫的完整性約束。(通過原子性,隔離性,持久性 AND 用戶的配合實現(xiàn)一致性)
    • 這表示寫入的資料必須完 全符合所有的預設規(guī)則,這包含資料的精確度、串聯(lián)性以及后續(xù)數據庫可以自發(fā)性地完成預定的工 作。
  • 隔離性(Isolation,又稱獨立性):事務之間的執(zhí)行是相互隔離的,一個事務的執(zhí)行不會受到其他事務的影響。
    • 允許多個并發(fā)事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務 并發(fā)執(zhí)行時由于交叉執(zhí)行而導致數據的不一致。
    • 事務隔離分為不同級別,包括讀未提交( Read uncommitted )、讀提交(read committed)、可重復讀( repeatable read )和串行化 ( Serializable
  • 持久性(Durability):一旦事務提交,其對數據庫所做的改變將是 永久性 的,即使系統(tǒng)發(fā)生故障也不會丟失。

2.2 為什么存在事務

剛才說的是多個 sql交叉執(zhí)行 可能會出現(xiàn) 并發(fā)問題 ,進而導致數據不一致,進而導致數據完整性,這都知道。但是對事務的理解不能光站在程序員角度理解,一定要站在數據庫使用者角度考慮。

  • 事務被 MySQL 編寫者設計出來,但是 事務 并不是天然就有的,而是在用一段時間發(fā)現(xiàn)要有這個 事務。本質是為了當應用程序訪問數據庫的時候,事務 能夠簡化我們的編程模型,不需要我們去考慮各種各樣的潛在錯誤和并發(fā)問題。
  • 只需要把告訴我你要干什么,把你的 sql 給我,我?guī)湍惴庋b成事務,幫你去運行??梢韵胍幌庐斘覀兪褂檬聞諘r,要么提交,要么回滾,我們不會去考慮網絡異常了,服務器宕機了,同時更改一個數據怎么辦對吧?這些問題統(tǒng)統(tǒng)不考慮。
  • 因此 事務 本質上是為了應用層服務的,是為了讓上層的應用服務更好的使用數據庫。而不是伴隨著數據庫系統(tǒng)天生就有的。

備注:我們后面把 MySQL 中的一行信息,稱為 一行記錄

總結

  • 解決并發(fā)問題:事務的設計初衷是為了應對并發(fā)操作帶來的數據不一致問題,確保數據的完整性和一致性。
  • 服務應用層:事務的本質是為應用層服務的,它簡化了開發(fā)者的編程模型,使開發(fā)者可以專注于業(yè)務邏輯,而不用擔心底層的數據操作細節(jié)。
  • 對來的一大批 SQL–打包成事務-- 先描述再組織 管理

2.3 事務的版本支持

  • 支持引擎:在MySQL中,只有使用了 InnoDB 數據庫引擎的數據庫或表才
  • 支持事務,MyISAM 不支持。

查看引擎

mysql> show engines \G;
# ...
*************************** 5. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: MyISAM storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
# ...
*************************** 7. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
# ...
9 rows in set (0.01 sec)

2.4 事務的提交方式

  • 自動提交:事務默認是自動提交的。
  • 手動提交

查看

show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+

設置

set autocommit=0; -- 設置為手動提交
set autocommit=1; -- 設置為自動提交

2.5 事務的常見操作方式

linux下 mysql 是一個命令行式的客戶端進程。但不僅如此 mysql 客戶端還有很多其他客戶端如圖形化界面版的,還有其他語言版的。

  • mysql 是一套網絡服務進程也就意味著除了本地主機,遠端主機也可以連接 myql

換句話說 mysql 服務器可能會被多個客戶端同時訪問

root@VM-8-10-ubuntu:/home/lighthouse# netstat -nltp; # 需要切換成 root 用戶
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      13847/mysqld            
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      823/sshd: /usr/sbin 

為了更好做事務方面演示,我們將 mysql 的默認隔離級別設置成讀未提交,隔離級別后面我們專門具體說。

設置全局事務隔離級別 讀為提交

set global transaction isolation level READ UNCOMMITTED;

需要重啟終端,進行查看,可以看到

mysql> quit
Bye
# 需要重啟終端,進行查看
mysql> select @@tx_isolation; # 5.0 版本
mysql> select @@transaction_isolation; # 8.0 版本
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-UNCOMMITTED        |
+-------------------------+
REPEATABLE-READ   # 默認是這個
  • 然后新起兩個 mysql 客戶端,為什么這么做呢,我們主要是為了研究事務,研究事務就要研究多個客戶端并發(fā)訪問的情況。
  • 其次 mysql 是有隔離性和隔離級別的,所以目前把隔離級別跳到最低,一個 mysql 做操作,另一個 mysql 就能看到。
  • 這樣很能清楚看到事務交叉所帶來的問題。

【案例】:

① 創(chuàng)建一個員工表

create table if not exists account(
	id int primary key,
	name varchar(50) not null default '',
	blance decimal(10,2) not null default 0.0
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

兩個 mysql客戶端 可以并發(fā)訪問這張表,準備工作全部就緒,下面我們來做試驗!

mysql> show processlist;
+------+-----------------+-----------+--------+---------+---------+------------------------+------------------+
| Id   | User            | Host      | db     | Command | Time    | State                  | Info             |
+------+-----------------+-----------+--------+---------+---------+------------------------+------------------+
|    5 | event_scheduler | localhost | NULL   | Daemon  | 4481367 | Waiting on empty queue | NULL             |
| 2385 | root            | localhost | learn3 | Query   |       0 | init                   | show processlist |
| 2386 | root            | localhost | learn3 | Sleep   |      41 |                        | NULL             |
+------+-----------------+-----------+--------+---------+---------+------------------------+------------------+

?正常演示 - 事務的開始與回滾

② 啟動事務

start transaction; -- 方式一
begin;  -- 方式二

③ 設置保存點

savepoint s1;

④ 回滾到保存點

rollback s1;

設置和回滾使用如下

⑤ 提交事務

如果想結束這個事務,那就提交一下,相當于把這個事務提交了

commit;

⑥ 回滾事務

  • 那我們以后是不是必須要設置保持點才能回滾呢?
  • 并不是!沒有保存點只是沒有辦法定向回滾了。但是可以直接回滾到最開始!
rollback;

直接回滾到最開始!然后數據就全沒了。即使是結束事務,回歸到單 sql 也是沒有的。

非正常操作

下面都是默認開啟 自動提交 的,而且 演示 1 和 演示 2 表開始的時候均無數據(empty)

非正常演示1: 證明未 commit ,客戶端崩潰,MySQL自動會回滾(隔離級別設置為讀未提交)

-- 終端A
begin; -- 開啟事務
insert into account values (1, '張三', 100); -- 插入記錄
mysql> select * from account; -- 數據已經存在,但沒有commit,此時同時查看終端B
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三    | 100.00 |
+----+--------+--------+

讓 A 中止,然后再查看A終止前后 B 的數據,如下:

mysql> Aborted -- ctrl + \ 異常終止MySQL
-- 終端B
mysql> select * from account; -- 終端 A 崩潰前
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三    | 100.00 |
+----+--------+--------+
1 row in set (0.00 sec)
mysql> select * from account; -- 終端 A 崩潰后
Empty set (0.00 sec)

上面我們發(fā)現(xiàn) 數據自動進行了回滾

非正常演示2 - 證明 commit 了,客戶端崩潰,MySQL數據不會在受影響,已經持久化

-- 終端 A
mysql> begin;                    -- 開啟事務
mysql> insert into account values (1, '張三', 100); -- 插入記錄
Query OK, 1 row affected (0.00 sec)
mysql> commit; -- 提交事務
Query OK, 0 rows affected (0.04 sec)
mysql> Aborted -- ctrl + \ 異常終止MySQL
-- 終端 A 終止后,切換終端 B 查看數據
mysql> select * from account;
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三    | 100.00 |
+----+--------+--------+
1 row in set (0.00 sec)

相比于上面這里我們在異常終止終端 A 之前,已經把數據 commit 了,然后再查看 B 發(fā)現(xiàn)數據還在,沒有回滾 – 持久化保存

  • 數據存在了,所以commit 的作用是將數據持久化到MySQL中

非正常演示3 - 對比演示 1。證明 begin 操作會自動更改提交方式,不會受 MySQL 是否自動提交影響

-- 終端 A,歷史是有數據的
mysql> select * from account; 
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三    | 100.00 |
+----+--------+--------+
-- 事務 A 開始時: 是默認自動提交的查
mysql> show variables like 'autocommit'; 
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)
-- 關閉自動提交
mysql> set autocommit=0; 
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+

然后再開始進行事務操作,如下:

mysql> begin; -- 開啟事務
mysql> insert into account values (2, '李四', 10000); -- 插入記錄
-- 在終端 A 中查看插入記錄
mysql> select *from account; 
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+

然后再次讓終端 A 異常終止,查看 A 終止前后 B 的數據,如下:

mysql> Aborted -- 再次異常終止 A 
-- 切換到終端 B
mysql> select * from account; -- 終端A崩潰前
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四   | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)
mysql> select * from account; -- 終端A崩潰后,自動回滾
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三    | 100.00 |
+----+--------+--------+

此時我們發(fā)現(xiàn),這個結果和 演示1 是類似的,可以知道 begin 與是否設置 set autocommit 無關,證明正確

④ 非正常演示4 - 證明單條 SQL 與事務的關系【autocommit】

實驗一:

-- 終端 A,開始時是有數據的
mysql> select * from account;
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三   | 100.00 |
+----+--------+--------+
mysql> set autocommit=0; -- 關閉自動提交
mysql> insert into account values (2, '李四', 10000); -- 插入記錄
Query OK, 1 row affected (0.00 sec)
mysql> select *from account; -- 在終端 A 中查看結果,已經插入。此時可以在查看終端B
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)
mysql> ^D Bye -- ctrl + \ or ctrl + d,終止終端 
-- 終端B
mysql> select * from account; -- 終端A崩潰前
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)
mysql> select * from account; -- 終端A崩潰后
+----+--------+--------+
| id | name   | blance |
+----+--------+--------+
| 1  | 張三   | 100.00 |
+----+--------+--------+

上面數據發(fā)生了回滾

實驗二:

-- 終端A
mysql> show variables like 'autocommit'; -- 開啟默認提交
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON     |
+---------------+-------+
1 row in set (0.00 sec)
mysql> insert into account values (2, '李四', 10000);
mysql> select * from account; -- 數據已經插入
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)
mysql> Aborted -- 異常終止
-- 終端B
mysql> select * from account; -- 終端A崩潰前
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+
mysql> select * from account; -- 終端A崩潰后,并不影響,已經持久化。autocommit起作用
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
| 1  | 張三    | 100.00   |
| 2  | 李四    | 10000.00 |
+----+--------+----------+

結論

  • 未提交時客戶端崩潰:事務可以手動回滾,同時操作異常時,MySQL 會自動回滾未提交的事務。
  • 已提交時客戶端崩潰:只要輸入begin 或者 start transaction,事務便必須要通過 commit 提交,才會持久化,與是否設置 set autocommit 無關
  • 單條SQL與事務:默認情況下,對于 InnoDB 每一條 SQL 語言都默認封裝成事務,自動提交。如果關閉自動提交,單條SQL語句也需要手動提交或回滾【select 有特殊情況,因為 MySQL 有 MVCC】

從上面的例子,我們能看到事務本身的原子性(回滾),持久性(commit)

注意事項

  • 回滾:如果沒有設置保存點,只能回滾到事務的開始,直接使用 rollback(前提是事務 還沒有提交)
  • 提交:事務提交后無法回滾。
  • 保存點:可以選擇回退到哪個保存點。
  • 版本支持InnoDB 支持事務, MyISAM 不支持事務
  • 啟動事務:可以使用 start transactionbegin

到此這篇關于MySQL 事務的概念及ACID屬性和使用詳解的文章就介紹到這了,更多相關mysql事務ACID屬性內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mysql日志文件之undo?log和redo?log

    mysql日志文件之undo?log和redo?log

    MySQL日志記錄了MySQL數據庫日常操作和錯誤信息,MySQL有不同類型的日志文件,下面這篇文章主要給大家介紹了關于mysql日志文件之undo?log和redo?log的相關資料,需要的朋友可以參考下
    2022-04-04
  • SQL中l(wèi)imit函數語法與用法(MYSQL獲取限制某行數據)

    SQL中l(wèi)imit函數語法與用法(MYSQL獲取限制某行數據)

    limit是MySql的內置函數,一般用于查詢表中記錄的條數,作用是用于限制查詢條數,下面這篇文章主要給大家介紹了關于SQL中l(wèi)imit函數語法與用法的相關資料,詳細講了MYSQL獲取限制某行數據的方法,需要的朋友可以參考下
    2022-08-08
  • php后臺經常提示無法連接mysql 刷新后又可以訪問的解決方法

    php后臺經常提示無法連接mysql 刷新后又可以訪問的解決方法

    這幾天有一臺MySQL數據庫服務器出現(xiàn)了頻繁的掉線情況,通過排查,并沒有排查出哪個網站被攻擊,百思不得其解中的時候,群里有個朋友說是因為微軟KB967723造成的,網上搜索了一下,果然很多人都是這樣的問題,都是windows系統(tǒng)下安裝的MySQL造成的
    2011-05-05
  • MySQL之高可用集群部署及故障切換實現(xiàn)

    MySQL之高可用集群部署及故障切換實現(xiàn)

    這篇文章主要介紹了MySQL之高可用集群部署及故障切換實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • mysql獲取排列序號的三種常用方法小結

    mysql獲取排列序號的三種常用方法小結

    這篇文章主要介紹了mysql獲取排列序號的三種常用方法,并通過代碼示例和圖文給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Mysql徹底解決中文亂碼問題的方案(Illegal mix of collations for operation)

    Mysql徹底解決中文亂碼問題的方案(Illegal mix of collations for operation)

    mysql數據庫和中文支持很不友好,經常見到“Illegal mix of collations for operation”錯誤,該如何解決呢?下面小編給大家?guī)砹薽ysql數據庫中涉及到哪些字符集及徹底解決中文亂碼的解決方案,非常不錯,一起看看吧
    2016-08-08
  • MySQL插入、更新與刪除表中數據實現(xiàn)方式

    MySQL插入、更新與刪除表中數據實現(xiàn)方式

    本文介紹了MySQL數據插入、更新和刪除的操作方法,包括直接添加、沒有字段名添加、部分字段添加、多行添加等插入方法,UPDATE語句更新記錄,DELETE語句刪除記錄,以及TRUNCATE語句刪除表中所有記錄,最后總結了TRUNCATE與DELETE的區(qū)別
    2026-04-04
  • MySQL主從集群的實現(xiàn)示例

    MySQL主從集群的實現(xiàn)示例

    本文主要介紹了MySQL主從集群的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-01-01
  • mysql索引失效的常見九種原因圖文詳解

    mysql索引失效的常見九種原因圖文詳解

    索引失效這個問題的前提應該是建立了索引,卻沒有使用到,或者沒有完全使用到,下面這篇文章主要給大家介紹了關于mysql索引失效的常見九種原因的相關資料,需要的朋友可以參考下
    2022-06-06
  • Windows?本地安裝?Mysql8.0圖文教程

    Windows?本地安裝?Mysql8.0圖文教程

    本文介紹了如何在Windows本地安裝Mysql8.0。從下載Mysql8.0安裝包,運行安裝程序,配置初始設置到啟動Mysql服務等詳細步驟進行了講解。
    2023-04-04

最新評論

凭祥市| 巩义市| 正阳县| 信丰县| 剑河县| 南乐县| 梁平县| 托克托县| 永德县| 江陵县| 旺苍县| 库伦旗| 沙坪坝区| 南阳市| 库尔勒市| 雷波县| 新泰市| 平阳县| 宜城市| 赣州市| 平昌县| 台安县| 天水市| 临清市| 霍林郭勒市| 汝城县| 滨海县| 太谷县| 北川| 贵德县| 华池县| 鸡西市| 隆安县| 渭源县| 鄯善县| 青田县| 乐清市| 重庆市| 克拉玛依市| 甘孜| 洮南市|