1. 程式人生 > >MySQL中的事務與鎖

MySQL中的事務與鎖

事務

資料庫事務(簡稱:事務)是資料庫管理系統執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。一個數據庫事務通常包含了一個序列的對資料庫的讀/寫操作。它的存在包含有以下兩個目的:

1
2
1. 為資料庫操作序列提供了一個從失敗中恢復到正常狀態的方法,同時提供了資料庫即使在異常狀態下仍能保持一致性的方法。
2. 當多個應用程式在併發訪問資料庫時,可以在這些應用程式之間提供一個隔離方法,以防止彼此的操作互相干擾。

當事務被提交給了DBMS(資料庫管理系統),則DBMS(資料庫管理系統)需要確保:

1
2
該事務中的所有操作都成功完成且其結果被永久儲存在資料庫中,如果事務中有的操作沒有成功完成,則事務中的所有操作都需要被回滾,
回到事務執行前的狀態;同時,該事務對資料庫或者其他事務的執行無影響,所有的事務都好像在獨立的執行。

Basically any time you have a unit of work that is either sensitive to outside changes or needs the ability to rollback every change, if an error occurs or some other reason.

ACID

並非任意的對資料庫的操作序列都是資料庫事務。資料庫事務擁有以下四個特性: 原子性(Atomiocity)、一致性(Consistency)、隔離性(Isolation)和永續性(Durability),習慣上被稱之為ACID特性。

  • 原子性(Atomicity)

一個事務中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。

  • 一致性(Consistency)

事務應確保資料庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是資料庫中的資料應滿足完整性約束。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、關聯性以及後續資料庫可以自發性地完成預定的工作,如兩使用者轉款前後的金額總和要一樣。

  • 隔離性(Isolation)

當兩個或者多個事務併發訪問(此處訪問指查詢和修改的操作)資料庫的同一資料時所表現出的相互關係。通常來說,一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對其他事務是隔離的,併發執行的各個事務之間互相不干擾。但事務之間的真實隔離性取決於事務的隔離模式。

SQL標準中定義了4中隔離級別(或稱為隔離模式),低級別的隔離可以執行更高的併發,系統的開銷也更低。這4種級別包括讀未提交(read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和序列化(serializable)。

此處輸入圖片的描述

給出每種隔離級別的實際程式碼例子

  • READ UNCOMMITTED(未提交讀)

該隔離級別下,事務中的修改,即使沒有提交,對其他事務也都是可見的。因此,對於其他業務,可能會產生“髒讀”,從而引起很多問題。同時從效能層面考慮,READ UNCOMMITED 和其他隔離級別也差不多,因此實際場景中一般很少使用。

髒讀: 讀取到部分修改的、事務未提交的資料, 即SELECT會讀取其他事務修改而還沒有提交的資料。比如:事務T1更新了一行記錄的內容,但是並沒有提交所做的修改;事務T2讀取更新後的行,然後T1執行回滾操作,取消了剛才所做的修改。現在T2所讀取的行就無效了。

  • READ COMMITTED(提交讀)

大多資料庫的預設隔離級別如Oracle,但MySQL不是。本隔離級別下,滿足隔離的基本定義:事務在提交前所做的修改對其他業務不可見。該級別下,兩次執行同樣的查詢,可能會得到不一樣的結果,產生不可重複讀的效果。

不可重複讀: SELECT的時候無法重複讀,即同一個事務中兩次執行同樣的查詢語句,若在第一次與第二次查詢之間時間段,其他事務又剛好修改了其查詢的資料且提交了,則兩次讀到的資料不一致。比如:事務T1讀取一行記錄,緊接著事務T2修改了T1剛才讀取的那一行記錄。然後T1又再次讀取這行記錄,發現與剛才讀取的結果不同。這就稱為“不可重複”讀,因為T1原來讀取的那行記錄已經發生了變化。

  • REPEATABLE READ(可重複讀)

MySQL預設隔離級別,該隔離級別解決了不可重複讀問題——SELECT的時候可以重複讀,即同一個事務中兩次執行同樣的查詢語句,得到的資料始終都是一致的,但還是存在幻讀。

可重複讀: 在同一個事務內的查詢都與事務開始時刻一致的,InnoDB預設級別。

幻讀: 事務T1讀取一條指定的WHERE子句所返回的結果集。然後事務T2新插入一行記錄,這行記錄恰好可以滿足T1所使用的查詢條件中的WHERE 子句的條件。然後T1又使用相同的查詢再次對錶進行檢索,但是此時卻看到了事務T2剛才插入的新行。這個新行就稱為“幻像”,因為對T1來說這一行就像突然出現的一樣。InnoDB 通過多版本併發控制(MVCC)解決幻讀問題。

  • SERIALIZE(可序列化)

強制事務序列執行。該隔離級別下,會對讀取的每一行資料上都加上鎖,因而對鎖機制的管理比較耗系統資源,資料庫一般都不會用這個隔離級別。與可重複讀的唯一區別是,預設把普通的SELECT語句改成SELECT …. LOCK IN SHARE MODE。即為查詢語句涉及到的資料加上共享瑣,阻塞其他事務修改真實資料。

在MySQL中,可以通過 select @@tx_isolation;命令檢視當前的事務隔離級別,如:

此處輸入圖片的描述

也可以通過執行命令set session transaction isolation level read committed;修改事務隔離級別,如:

此處輸入圖片的描述

此處輸入圖片的描述

需要注意的是上述方式修改的事務隔離級別僅對當前session有效。如果要對所有新建的連線設定隔離級別,可以用set global transaction isolation level read committed; 它將決定新建連線的初始隔離級,但不會改變已有連線的隔離級。可以通過select @@global.tx_isolation;命令檢視global transaction isolation level:

此處輸入圖片的描述

如果想要全域性修改事務隔離級別,可以在my.cnf 配置檔案中修改,只需在最後加上”

1
2
3
#可選引數有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
[mysqld]
transaction-isolation = READ-UNCOMMITTED
  • 永續性(Durability)

已被提交的事務對資料庫的修改應該永久儲存在資料庫中,接下來其他的其他操作或故障不應該對其執行結果有任何影響,即提交的事務一定保證寫入磁碟。

事務的實現

1. 如何保證原子性(A)?

資料庫中與原子性相關的操作有rollback和commit。commit用於正常提交一個事務,rollback用於將事務中之前的操作回滾。第三種情況是資料庫出現異常時,如斷電,事務執行一半而退出。 事務的整個執行過程說明如下: (1) 每個事務開始時,系統會為該事務分配一個時間戳(唯一標識該事務)、回滾段和undo段。 (2) 事務中的每條SQL在執行修改操作前都會寫undo日誌,然後再將更新的內容寫入undo段。 (3) 執行commit時,系統將修改的資料寫入實際記憶體,並將修改資訊寫入回滾段。 (4) 執行rollback時,系統將undo段內容失效。 (5) 當系統在執行事務過程中出現異常退出後,系統再次啟動,會從undo日誌中恢復。

2. 如何保證一致性(C)?

事務一致性的保證和原子性和隔離性都有關係,即系統保證事務一致性的前提是保證事務的原子性和隔離性。上文中的“髒讀”、“不可重複讀”、“幻讀”,其實都是資料庫讀一致性問題,必須由資料庫提供一定的事務隔離機制來解決。

3. 如何保證隔離性(I)?

目前資料庫實現的事務隔離方式分兩種:

1
2
3
1、基於悲觀併發控制思想: 在讀取資料前,對其加鎖,阻止其他事務讀資料進行修改。
2、基於樂觀併發控制思想:不加任何鎖,通過一定的機制生成一個數據請求時間點的一致性資料快照(snapshot),
並用這個快照來提供一定級別(語句級或事務級)的一致性讀取。
  • 悲觀併發控制

悲觀併發控制,正如其名,它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中(當前事務中),將資料處於鎖定狀態,即讀取資料時給加鎖,其它事務無法修改這些資料,修改刪除資料時也要加鎖,其它事務無法讀取這些資料。那只有當這個事務把鎖釋放,其他事務才能夠執行與該鎖衝突的操作。

悲觀鎖的實現,往往依靠資料庫提供的鎖機制(Lock-Based Concurrency Control)(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

悲觀併發控制主要用於資料爭用激烈的環境,以及發生併發衝突時使用鎖保護資料的成本要低於回滾事務的成本的環境中。然而,資料庫又是個高併發的應用,同一時間會有大量的併發訪問,如果加鎖過度,會極大的降低併發處理能力,於是就有了樂觀併發控制(又名“樂觀鎖”,Optimistic Concurrency Control,縮寫“OCC”)。

  • 樂觀併發控制

在關係資料庫管理系統裡,樂觀併發控制(又名“樂觀鎖”,Optimistic Concurrency Control,縮寫“OCC”)是一種併發控制的方法。相對悲觀鎖而言,樂觀鎖機制採取了更加寬鬆的加鎖機制。它假設多使用者併發的事務在處理時不會彼此互相影響,各事務能夠在不產生鎖的情況下處理各自影響的那部分資料。在提交資料更新之前,每個事務會先檢查在該事務讀取資料後,有沒有其他事務又修改了該資料。如果其他事務有更新的話,正在提交的事務會進行回滾。

樂觀併發控制多數用於資料爭用不大、衝突較少的環境中,這種環境中,偶爾回滾事務的成本會低於讀取資料時鎖定資料的成本,因此可以獲得比其他併發控制方法更高的吞吐量。

樂觀鎖,大多是基於MVCC (Multi-Version Concurrency Control),即多版本控制協議實現。MVCC最大的好處是讀不加鎖,讀寫不衝突。不加任何鎖,通過一定的機制生成一個數據請求時間點的一致性資料快照(snapshot),並用這個快照來提供一定級別(語句級或事務級)的一致性讀取。從使用者角度來看,好像是資料庫可以提供同一資料的多個版本,因此這種技術又叫做多版本併發控制(Mutil Version Concurrency Control,簡稱MVCC或MCC),也稱為多版本資料庫。 在讀多寫少的OLTP應用中,讀寫不衝突是非常重要的,極大的增加了系統的併發效能,這也是為什麼現階段,幾乎所有的RDBMS,都支援了MVCC。要說明的是,MVCC的實現沒有固定的規範,每個資料庫都會有不同的實現方式,這裡討論的是InnoDB的MVCC。

4. 如何保證永續性(D)?

永續性的保證需要日誌的支援,資料庫寫日誌的原則是執行寫資料前要先寫日誌。

針對事務一些推薦的做法

  • 開啟新事務前先rollback一下
  • 每次做完update後校驗affected_rows是否是期望的
  • 考慮重連邏輯
  • 儘量避免大事務
  • 加鎖資源使用要有一定的順序, 避免死鎖
  • mysql的事務儘量小,使用完,立即commit或rollback.不要起一個過大的事務
  • 避免嘗試去鎖一個不存在的記錄,for update語句where條件請使用主鍵
  • 避免過多的for update集合
  • mysql單表記錄保持在1000W以下,以獲得較好的效能
  • 需要修改mysql 鎖等待時間,避免for update等待時間超長,造成系統阻塞。innodb_lock_wait_timeout 引數

鎖就是事務T在對某個資料物件例如表、記錄等操作之前,先向系統發出請求,對其加鎖。加鎖後事務T就對該資料物件有了一定的控制。當多個客戶端同時訪問和修改相同的資料時,鎖機制可以保證資料的一致性。

InnoDB的鎖結構如下:

1
2
3
4
5
6
7
8
9
10
11
12
/* lock_struct結構用於描述InnoDB的鎖,其中一條記錄由多個結點組成 */
struct lock_struct{
  trx_t*    trx;    /* 擁有該鎖的事務 */
  UT_LIST_NODE_T(lock_t)  trx_locks;  /* 該事務的所有鎖 */
  ulint   type_mode;  /*鎖型別 */
  hash_node_t hash
            
           

相關推薦

MySQL(一):MySQL資料庫事務

#基本概念 事務是指滿足ACID特性的的一組操作,可以通過Commit提交事務,也可以也可以通過Rollback進行回滾。會存在中間態和一致性狀態(也是真正在資料庫表中存在的狀態) #ACID + **Atomicity【原子性】**:事務被視為不可分割的最小單元,事務的所有操作要麼全部提交成功,要麼全部失敗

MySQL事務

事務 資料庫事務(簡稱:事務)是資料庫管理系統執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。一個數據庫事務通常包含了一個序列的對資料庫的讀/寫操作。它的存在包含有以下兩個目的: 1 2

SQL Server事務

ani 否則 編譯 什麽 高並發 設置時間 檢測 isolation 管理 了解事務和鎖 事務:保持邏輯數據一致性與可恢復性,必不可少的利器。 鎖:多用戶訪問同一數據庫資源時,對訪問的先後次序權限管理的一種機制,沒有他事務或許將會一塌糊塗,不能保證數據的安全正確讀寫。 死鎖

MySQL 事務機制

mysql下表展示了本人安裝的MariaDB(10.1.19,MySQL的分支)所支持的所有存儲引擎概況,其中支持事務的有InnoDB、SEQUENCE,另外InnoDB還支持XA事務,MyISAM不支持事務。鎖可以通過SQL語句(如 LOCK TABLES )顯式申請,也可以由InnoDB引擎自動為你獲取。

T-SQL查詢進階--SQL Server事務

錯誤 span 設備 限制 數據復制 默認 base 數據 insert 為什麽需要鎖在任何多用戶的數據庫中,必須有一套用於數據修改的一致的規則,當兩個不同的進程試圖同時修改同一份數據時,數據庫管理系統(DBMS)負責解決它們之間潛在的沖突。任何關系數據庫必須支持事務的AC

RedisMySQL事務的區別

1、mysql中只有使用了InnoDB引擎的資料庫或表才支援事務; 2、使用“事務”的目的是:統一管理insert,update,delete這些寫操作,以此來維護資料的完整性。 事務命令 mysql: begin #顯式地開啟一個事務 commit #提交

MySQL事務詳解

事務 事務支援ACID特性 A原子性:所有操作要麼都做要麼都不做 C一致性:事務將資料庫從一種狀態變為另一種狀態一致性,保證資料庫完整性約束,例如唯一索引約束等 I隔離性:事務與事務之間是不可見的 D永續性:事務一旦提交那麼事務就是永久性的 ANSI/ISO SQL標準定義了4中

MySQL——事務詳解

事務與鎖詳解 1.事務的定義 一系列的資料庫操作,這些操作必須全部執行,否則全部不執行。例如一些和銀行賬戶存取相關的資料庫操作,必須得保證每一個操作得執行。 2.事務衝突——贓讀、不可重複讀、幻讀 由於為了加快資料庫的操作,需要資料庫支援併發,這樣就可能會產生多

Redis之坑:RedisMySQL事務的區別

Note: 該篇討論的只是Redis與MySQL中事務的區別,並不能統一代表NO-SQL與關係型SQL; 在 MySQL 中只有使用了 Innodb 資料庫引擎的資料庫或表才支援事務; 事務使用

mysql的共享排他

在 MySQL中的行級鎖,表級鎖,頁級鎖中介紹過,行級鎖是Mysql中鎖定粒度最細的一種鎖,行級鎖能大大減少資料庫操作的衝突。行級鎖分為共享鎖和排他鎖兩種,本文將詳細介紹共享鎖及排他鎖的概念、使用方式及注意事項等。 共享鎖(Share Lock) 共享鎖又稱讀鎖,

Mysql事務隔離級別binlog_format的一點理解

    之前幾年的軟體開發,總是離不開Oracle,涉及的各大專案中使用的資料庫也大多為Oracle,偶爾遇到Mysql也是簡單的使用,一直覺得Mysql很小型也很簡單,對其的理解也處於皮毛階段,最近遇到了一些Mysql的問題,對其中的事務隔離級別,以及binlog_for

分布式緩存技術redis學習系列(三)——redis高級應用(主從、事務、持久化)

master ica not ood www working can 出了 owin 上文《詳細講解redis數據結構(內存模型)以及常用命令》介紹了redis的數據類型以及常用命令,本文我們來學習下redis的一些高級特性。 回到頂部 安全性設置 設置客戶端操作秘密

MySQL(二)--事務視圖

atom enc 消失 ability count 事務 統計 tran 操作 一、事務 1、提交 2、回滾 3、ACID特性 二、視圖 1、創建視圖 2、刪除視圖 3、更新視圖 4、使用視圖 三、子查詢 1、 使用子查詢

MySQL事務事務隔離

mysql innodb transactions 事務隔離 MySQL中自從引入InnoDB引擎後,在MySQL中就支持事務,事務就是一組原子性的查詢語句,也即將多個查詢當作一個獨立的工作單元,平時通過提交工作單元來完成在事務中的相應的查詢或修改,在能支持事務的數據庫中必須要滿足ACI

【SQL】- 基礎知識梳理(八) - 事務

隔離性 rep del 數據表 訪問 關系 snapshot 轉換 pro 事務的概念 事務:若幹條T-SQL指令組成的一個操作數據庫的最小執行單元,這個整體要麽全部成功,要麽全部失敗。(並發控制) 事務的四個屬性:原子性、一致性、隔離性、持久性。稱為事務的ACID特性。

事務4.3-事務

sele 字段 防止 對數 實際應用 影響 功能 更新 read 數據庫和操作系統一樣,是一個多用戶使用的共享資源。當多個用戶並發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。若對並發操作不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性。加鎖是實

MySQLlimitmax同時使用時查詢為空的情況

嵌套查詢 下使用 spa get name ack question 使用 如果 一般情況下使用limit進行分頁時通常是第一頁就用max和min這些函數去求值,這樣的情況是正常的,但是如果limit去到了第二頁的時候發現這樣用是不行的,原因未知! 修改的方式如下,適合大

『淺入深出』MySQL 事務的實現

一點 隨著 保留 partially 並不會 它的 事件 all previous 在關系型數據庫中,事務的重要性不言而喻,只要對數據庫稍有了解的人都知道事務具有 ACID 四個基本屬性,而我們不知道的可能就是數據庫是如何實現這四個屬性的;在這篇文章中,我們將對事務的實現進

MySQLMyISAMInnoDB區別及選擇,mysql添加外鍵

title 必須 pan 就會 默認 簡化 平臺 兩種 myisam InnoDB:支持事務處理等不加鎖讀取支持外鍵支持行鎖不支持FULLTEXT類型的索引不保存表的具體行數,掃描表來計算有多少行DELETE 表時,是一行一行的刪除InnoDB 把數據和索引存放在表空間裏面

【SqlServer系列】淺談SQL Server事務(上篇)

架構 tab 要求 允許 ble 1.2 定義 由於 數據庫引擎 一 概述 在數據庫方面,對於非DBA的程序員來說,事務與鎖是一大難點,針對該難點,本篇文章試圖采用圖文的方式來與大家一起探討。 “淺談SQL Server 事務與鎖”這個專題共分