什麼是 SQL 事務,如何創建 SQL 事務

来源:https://www.cnblogs.com/vin-c/archive/2022/06/09/16360081.html
-Advertisement-
Play Games

本文給大家介紹資料庫中用來管理數據更新的重要概念——SQL 事務。簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合。 本文重點 事務是需要在同一個處理單元中執行的一系列更新處理的集合。通過使用事務,可以對資料庫中的數據更新處理的提交和取消進行管理。 事務處理的終止指令包括 COMM ...


目錄

本文給大家介紹資料庫中用來管理數據更新的重要概念——SQL 事務。簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合。

本文重點

  • 事務是需要在同一個處理單元中執行的一系列更新處理的集合。通過使用事務,可以對資料庫中的數據更新處理的提交和取消進行管理。

  • 事務處理的終止指令包括 COMMIT(提交處理)和 ROLLBACK(取消處理)兩種。

  • DBMS 的事務具有原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)四種特性。通常將這四種特性的首字母結合起來,統稱為 ACID 特性。

一、什麼是事務

估計有些讀者對事務(transaction)這個詞並不熟悉,它通常被用於商務貿易或者經濟活動中,但是在 RDBMS 中,事務是對錶中數據進行更新的單位。簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合

SQL 如何插入、刪除和更新數據 所述,對錶進行更新需要使用 INSERTDELETE 或者 UPDATE 三種語句。

但通常情況下,更新處理並不是執行一次就結束了,而是需要執行一系列連續的操作。這時,事務就能體現出它的價值了。

說到事務的例子,請大家思考一下下述情況。

現在,請大家把自己想象為管理 Product(商品)表的程式員或者軟體工程師。銷售部門的領導對你提出瞭如下要求。

“某某,經會議討論,我們決定把 運動 T 恤 的銷售單價下調 1000 元,同時把 T 恤衫 的銷售單價上浮 1000 元,麻煩你去更新一下資料庫。”

由於大家已經學習了更新數據的方法——只需要使用 UPDATE 進行更新就可以了,所以肯定會直接回答“知道了,請您放心吧”。

此時的事務由如下兩條更新處理所組成。

  • 更新商品信息的事務

    ① 將 運動 T 恤 的銷售單價降低 1000

    UPDATE Product
    SET sale_price = sale_price - 1000
    WHERE product_name = '運動T恤';
    

    ② 將 T 恤衫 的銷售單價上浮 1000

    UPDATE Product
    SET sale_price = sale_price + 1000
    WHERE product_name = 'T恤衫';
    

上述 ① 和 ② 的操作一定要作為同一個處理單元執行。

如果只執行了 ① 的操作而忘記了執行 ② 的操作,或者反過來只執行了 ② 的操作而忘記了執行 ① 的操作,一定會受到領導的嚴厲批評。

遇到這種需要在同一個處理單元中執行一系列更新操作的情況,一定要使用事務來進行處理。

法則 7

事務是需要在同一個處理單元中執行的一系列更新處理的集合。

一個事務中包含多少個更新處理或者包含哪些處理,在 DBMS 中並沒有固定的標準,而是根據用戶的要求決定的(例如,運動 T 恤T 恤衫 的銷售單價需要同時更新這樣的要求,DBMS 是無法瞭解的)。

二、創建事務

如果想在 DBMS 中創建事務,可以按照如下語法結構編寫 SQL 語句。

語法 6 事務的語法

事務開始語句;

      DML語句①;
      DML語句②;
      DML語句③;
         .
         .
         .
事務結束語句(COMMIT或者ROLLBACK);

使用事務開始語句和事務結束語句,將一系列 DML 語句(INSERT/UPDATE/DELETE 語句)括起來,就實現了一個事務處理。

這時需要特別註意的是事務的開始語句 [1]。實際上,在標準 SQL 中並沒有定義事務的開始語句,而是由各個 DBMS 自己來定義的。比較有代表性的語法如下所示。

  • SQL Server、PostgreSQL

    BEGIN TRANSACTION

  • MySQL

    START TRANSACTION

  • Oracle、DB2

例如使用之前的那兩個 UPDATE(① 和 ②)創建出的事務如代碼清單 21 所示。

代碼清單 21 更新商品信息的事務

SQL Server PostgreSQL

BEGIN TRANSACTION;

    -- 將運動T恤的銷售單價降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '運動T恤';

    -- 將T恤衫的銷售單價上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';

COMMIT;

MySQL

START TRANSACTION;

    -- 將運動T恤的銷售單價降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '運動T恤';

    -- 將T恤衫的銷售單價上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';

COMMIT;

Oracle DB2

-- 將運動T恤的銷售單價降低1000日元
UPDATE Product
   SET sale_price = sale_price - 1000
 WHERE product_name = '運動T恤';

-- 將T恤衫的銷售單價上浮1000日元
UPDATE Product
   SET sale_price = sale_price + 1000
 WHERE product_name = 'T恤衫';

COMMIT;

如上所示,各個 DBMS 事務的開始語句都不盡相同,其中 Oracle 和 DB2 並沒有定義特定的開始語句。

可能大家覺得這樣的設計很巧妙,其實是因為標準 SQL 中規定了一種悄悄開始事務處理 [2] 的方法。

因此,即使是經驗豐富的工程師也經常會忽略事務處理開始的時間點。大家可以試著通過詢問“是否知道某個 DBMS 中事務是什麼時候開始的”,來測試學校或者公司前輩的資料庫知識。

反之,事務的結束需要用戶明確地給出指示。結束事務的指令有如下兩種。

  • COMMIT——提交處理

    COMMIT 是提交事務包含的全部更新處理的結束指令(圖 3),相當於文件處理中的覆蓋保存。一旦提交,就無法恢復到事務開始前的狀態了。

    因此,在提交之前一定要確認是否真的需要進行這些更新。

    COMMIT 的流程 = 直線進行

    圖 3 COMMIT 的流程 = 直線進行

    萬一由於誤操作提交了包含錯誤更新的事務,就只能回到重新建表、重新插入數據這樣繁瑣的老路上了。

    由於可能會造成數據無法恢復的後果,請大家一定要註意(特別是在執行 DELETE 語句的 COMMIT 時尤其要小心)。

    法則 8

    雖然我們可以不清楚事務開始的時間點,但是在事務結束時一定要仔細進行確認。

  • ROLLBACK——取消處理

    ROLLBACK 是取消事務包含的全部更新處理的結束指令(圖 4),相當於文件處理中的放棄保存。一旦回滾,資料庫就會恢復到事務開始之前的狀態(代碼清單 22)。

    通常回滾並不會像提交那樣造成大規模的數據損失。

    ROLLBACK 的流程 = 掉頭回到起點

    圖 4 ROLLBACK 的流程 = 掉頭回到起點

    代碼清單 22 事務回滾的例子

    SQL Server PostgreSQL

    BEGIN TRANSACTION; ------------------- ①
    
        -- 將運動T恤的銷售單價降低1000日元
        UPDATE Product
        SET sale_price = sale_price - 1000
        WHERE product_name = '運動T恤';
    
        -- 將T恤衫的銷售單價上浮1000日元
        UPDATE Product
        SET sale_price = sale_price + 1000
        WHERE product_name = 'T恤衫';
    
    ROLLBACK;
    

    特定的 SQL

    至此,我們已經知道各個 DBMS 中關於事務的語法不盡相同。

    代碼清單 22 中的語句在 MySQL 中執行時需要將 ① 語句改寫為“START TRANSACTION”,而在 Oracle 和 DB2 中執行時則無需 ① 語句(請將其刪除),具體請參考上一節的“創建事務”。

    上述事務處理執行之後,表中的數據不會發生任何改變。這是因為執行最後一行的 ROLLBACK 之後,所有的處理都被取消了。

    因此,回滾執行起來就無需像提交時那樣小心翼翼了(即使是想要提交的情況,也只需要重新執行事務處理就可以了)。

專欄

事務處理何時開始

之前我們說過,事務並沒有標準的開始指令存在,而是根據 DBMS 的不同而不同。

實際上,幾乎所有的資料庫產品的事務都無需開始指令。這是因為大部分情況下,事務在資料庫連接建立時就已經悄悄開始了,並不需要用戶再明確發出開始指令。

例如,使用 Oracle 時,資料庫連接建立之後,第一條 SQL 語句執行的同時,事務就已經悄悄開始了。

像這樣不使用指令而悄悄開始事務的情況下,應該如何區分各個事務呢?通常會有如下兩種情況。

A:每條 SQL 語句就是一個事務(自動提交模式

B:直到用戶執行 COMMIT 或者 ROLLBACK 為止算作一個事務

通常的 DBMS 都可以選擇其中任意一種模式。預設使用自動提交模式的 DBMS 有 SQL Server、PostgreSQL 和 MySQL 等 13 DML 語句如下所示,每一條語句都括在事務的開始語句和結束語句之中。

BEGIN TRANSACTION;
   -- 將運動T恤的銷售單價降低1000日元
   UPDATE Product
      SET sale_price = sale_price - 1000
    WHERE product_name = '運動T恤';
COMMIT;

BEGIN TRANSACTION;
   -- 將T恤衫的銷售單價上浮1000日元
   UPDATE Product
      SET sale_price = sale_price + 1000
    WHERE product_name = 'T恤衫';
COMMIT;

在預設使用 B 模式的 Oracle 中,事務都是直到用戶自己執行提交或者回滾指令才會結束。

自動提交的情況需要特別註意的是 DELETE 語句。

如果不是自動提交,即使使用 DELETE 語句刪除了數據表,也可以通過 ROLLBACK 命令取消該事務的處理,恢復表中的數據。

但這僅限於明示開始事務,或者關閉自動提交的情況。如果不小心在自動提交模式下執行了 DELETE 操作,即使再回滾也無濟於事了。

這是一個很嚴重的問題,初學者難免會碰到這樣的麻煩。一旦誤刪了數據,如果無法重新插入,是不是想哭的心都有了?所以一定要特別小心。

三、ACID 特性

DBMS 的事務都遵循四種特性,將這四種特性的首字母結合起來統稱為 ACID 特性。這是所有 DBMS 都必須遵守的規則。

  • 原子性(Atomicity)

    原子性是指在事務結束時,其中所包含的更新處理要麼全部執行,要麼完全不執行,也就是要麼占有一切要麼一無所有。

    例如,在之前的例子中,在事務結束時,絕對不可能出現 運動 T 恤 的價格下降了,而 T 恤衫 的價格卻沒有上漲的情況。

    該事務的結束狀態,要麼是兩者都執行了(COMMIT),要麼是兩者都未執行(ROLLBACK)。

    從事務中途停止的角度去考慮,就能比較容易理解原子性的重要性了。

    由於用戶在一個事務中定義了兩條 UPDATE 語句,DBMS 肯定不會只執行其中一條,否則就會對業務處理造成影響。

  • 一致性(Consistency)

    一致性指的是事務中包含的處理要滿足資料庫提前設置的約束,如主鍵約束或者 NOT NULL 約束等。

    例如,設置了 NOT NULL 約束的列是不能更新為 NULL 的,試圖插入違反主鍵約束的記錄就會出錯,無法執行。

    對事務來說,這些不合法的 SQL 會被回滾。也就是說,這些 SQL 處理會被取消,不會執行。

    一致性也稱為完整性(圖 5)。

    保持完整性的流程

    圖 5 保持完整性的流程

  • 隔離性(Isolation)

    隔離性指的是保證不同事務之間互不幹擾的特性。該特性保證了事務之間不會互相嵌套。此外,在某個事務中進行的更改,在該事務結束之前,對其他事務而言是不可見的。

    因此,即使某個事務向表中添加了記錄,在沒有提交之前,其他事務也是看不到新添加的記錄的。

  • 持久性(Durability)

    持久性也可以稱為耐久性,指的是在事務(不論是提交還是回滾)結束後,DBMS 能夠保證該時間點的數據狀態會被保存的特性。

    即使由於系統故障導致數據丟失,資料庫也一定能通過某種手段進行恢復。

    如果不能保證持久性,即使是正常提交結束的事務,一旦發生了系統故障,也會導致數據丟失,一切都需要從頭再來。

    保證持久性的方法根據實現的不同而不同,其中最常見的就是將事務的執行記錄保存到硬碟等存儲介質中(該執行記錄稱為日誌)。

    當發生故障時,可以通過日誌恢復到故障發生前的狀態。

原文鏈接:https://www.developerastrid.com/sql/what-is-sql-transaction/

(完)


  1. 與之相對,事務結束語句只有 COMMITROLLBACK 兩種,在所有的 RDBMS 中都是通用的。 ↩︎

  2. 《標準 SQL 手冊修訂第 4 版》中的記述:希望大家註意事務預設開始的時間點。沒有“BEGIN TRANSACTION”這樣明確的開始標誌。 ↩︎


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

-Advertisement-
Play Games
更多相關文章
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 一、安裝vmware虛擬機 個人使用可獲得免費許可證,註冊用戶激活即可。 激活成功獲得免費許可證後登陸自己的用戶進官網下載鏈接: 下載完成後,一直下一步即可安裝成功。 二、Centos8 鏡像支持M1晶元 三、安裝Centos8 系統 1、打開虛 ...
  • LNMP是Linux+Nginx+Mysql+PHP所構建的一個動態開發環鏡 我這裡使用的系統是華為的OpenEnler系統,使用了Nginx1.12版本、Mysql8和PHP7.4 如果有出錯的地方可能是作者沒做到位,見諒 安裝依賴包並安裝nginx: # mount /dev/cdrom /mn ...
  • 本文講解Linux伺服器 Ubuntu20.04 設置靜態IP方法。 ...
  • 英文原文: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html CPU Accounting Controller CPU統計控制器(CPU Accounting Controller)用來分組使用cgr ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡巴巴開源鏡像站 前言 最近,學習了胡老師的《ROS入門21講》,在Ubuntu18.04上安裝ROS過程中遇到了一些問題,解決這些問題耗費了大半天,故通過本文進行詳細安裝介紹,以便其他學者在安裝這塊少花時間,把更多的精力放在研究上。 一、環境配置 我的環境:虛 ...
  • 作用:命令行多視窗顯示;命令行程式與本機脫離 1 安裝tmux (1)redhat、centos系統 yum install tmux (2)ubuntu系統 apt-get install tmux 2 使用tmux (1)啟動 首先,我們使用遠程登錄工具,登錄到遠程伺服器上,然後執行下麵的命令: ...
  • 虛擬機關鍵配置名詞解釋 虛擬⽹絡編輯器 橋接模式 可以訪問互聯⽹,配置的地址信息和物理主機⽹段地址信息相同,容易造成地址衝突 NAT模式 可以訪問互聯⽹,配置的地址信息和物理主機⽹段地址信息不同,造成不了地址衝突 僅主機模式 不可以訪問互聯⽹,獲取地址主要⽤於虛擬主機之間溝通,但不能訪問外部⽹絡 網 ...
  • 亂序問題 在業務編寫 FlinkSQL 時, 非常常見的就是亂序相關問題, 在出現問題時,非常難以排查,且無法穩定復現,這樣無論是業務方,還是平臺方,都處於一種非常尷尬的地步。 亂序問題 在業務編寫 FlinkSQL 時, 非常常見的就是亂序相關問題, 在出現問題時,非常難以排查,且無法穩定復現,這 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...