首頁 資料庫 mysql教程 mysql資料庫中鎖機制的詳細介紹

mysql資料庫中鎖機制的詳細介紹

Sep 10, 2018 pm 02:12 PM
鎖機制

這篇文章帶給大家的內容是關於mysql資料庫中鎖機制的詳細介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

悲觀鎖與樂觀鎖:
悲觀鎖:顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,例如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

樂觀鎖:顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號碼等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像資料庫如果提供類似write_condition機制的其實都是提供的樂觀鎖。

表級:引擎 MyISAM,直接鎖定整張表,在你鎖定期間,其它進程無法對該表進行寫入操作。如果你是寫鎖,則其它進程則讀也不允許

頁級:引擎 BDB,表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄

行級:引擎INNODB, 僅對指定的記錄進行加鎖,這樣其它進程還是可以對同一個表中的其它記錄進行操作。

上述三種鎖定的特​​性大致可歸納如下:
1) 表級鎖定:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖定衝突的機率最高,並發度最低。
2) 頁面鎖定:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,並發度一般。
3) 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,並發度也最高。

三種鎖各有各的特點,若僅從鎖的角度來說,表級鎖更適合於以查詢為主,只有少量依索引條件更新資料的應用,如WEB應用;行級鎖定更適合於有大量按索引條件並發更新少量不同數據,同時又有並發查詢的應用,如一些在線事務處理(OLTP)系統。 

MySQL表格層級鎖定有兩種模式:
1、表格共享讀取鎖定(Table Read Lock)。對MyISAM表進行讀取操作時,它不會阻塞其他使用者對相同表的讀取請求,但會阻塞 對同一表的寫入操作;
2、表獨佔寫鎖(Table Write Lock)。對MyISAM表的寫入操作,則會阻塞其他使用者對相同表的讀取和寫入操作。

MyISAM表的讀取和寫入是串列的,即進行讀取操作時不能進行寫入操作,反之也是一樣。但在一定條件下MyISAM表也支援查詢和插入的操作的並發進行,其機制是透過控制一個系統變數(concurrent_insert)來進行的,當其值設為0時,不允許並發插入;當其值設定為1時,如果MyISAM表中沒有空洞(即表中沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄;當其值設定為2時,無論MyISAM表中有沒有空洞,都允許在表尾並發插入記錄。

MyISAM鎖定調度是如何實現的呢,這也是一個很關鍵的問題。例如,當一個行程請求某個MyISAM表的讀鎖,同時另一個行程也請求同一表的寫鎖,此時mysql將會如優先處理程序呢?透過研究表明,寫入進程將先獲得鎖(即使讀取請求先到鎖等待隊列)。但這也造成一個很大的缺陷,即大量的寫入操作會造成查詢操作很難獲得讀鎖,從而可能造成永遠阻塞。所幸我們可以透過一些設定來調節MyISAM的調度行為。我們可透過指定參數low-priority-updates,使MyISAM預設引擎給予讀取請求以優先的權利,設定其值為1(set low_priority_updates=1),使優先權降低。

InnoDB鎖定與MyISAM鎖定的最大不同在於:
1、是支援事務(TRANCSACTION)。
2、是採用了行級鎖定。

我們知道事務是由一組SQL語句組成的邏輯處理單元,其有四個屬性(簡稱ACID屬性),分別為:
原子性(Atomicity):事務是一個原子操作單元,其對資料的修改,要麼全部執行,要麼全都不執行;
一致性(Consistent):在交易開始和完成時,資料都必須保持一致狀態;
隔離性(Isolation) :資料庫系統提供一定的隔離機制,確保事務在不受外部並發操作影響的「獨立」環境執行;
持久性(Durable):事務完成之後,它對於資料的修改是永久性的,即使出現系統故障也能夠維持。

並發事務處理帶來的問題
相對於串行處理來說,並發事務處理能大大增加資料庫資源的利用率,提高資料庫系統的事務吞吐量,從而可以支援更多的使用者。但並發事務處理也會帶來一些問題,主要包括以下幾種情況。
1、更新遺失(Lost Update):當兩個或多個交易選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生遺失更新問題-最後的更新覆蓋了其他事務所所做的更新。例如,兩位編輯人員製作了同一文件的電子副本。每個編輯人員獨立地更改其副本,然後保存更改後的副本,這樣就覆蓋了原始文件。最後儲存其更改副本的編輯人員會覆蓋另一個編輯人員所做的更改。如果在一個編輯人員完成並提交事務之前,另一個編輯人員無法存取相同文件,則可避免此問題。
2、髒讀(Dirty Reads):一個事務正在對一筆記錄做修改,在這個事務完成並提交前,這條記錄的資料就處於不一致狀態;這時,另一個事務也來讀取同一筆記錄,如果不加控制,第二個事務讀取了這些「髒」數據,並據此做進一步的處理,就會產生未提交的數據依賴關係。這種現像被形像地叫做」臟讀」。
3、不可重複讀(Non-Repeatable Reads):一個事務在讀取某些數據後的某個時間,再次讀取以前讀過的數據,卻發現其讀出的數據已經發生了改變、或某些記錄已經刪除了!這種現象就叫做「不可重複讀」。
4、幻讀(Phantom Reads):一個事務以相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的新數據,這種現象就稱為「幻讀”。

事務隔離等級
在上面講到的並發事務處理所帶來的問題中,「更新遺失」通常是應該完全避免的。但防止更新遺失,並不能單靠資料庫事務控制器來解決,需要應用程式對要更新的資料加必要的鎖定來解​​決,因此,防止更新遺失應該是應用程式的責任。
“髒讀”、“不可重複讀”和“幻讀”,其實都是資料庫讀取一致性問題,必須由資料庫提供一定的事務隔離機制來解決。資料庫實現事務隔離的方式,基本上可分為以下兩種。
1、一種是在讀取資料前,加鎖,阻止其他事務對資料進行修改。
2、另一種是不用加任何鎖,透過一定機制產生一個資料請求時間點的一致性資料快照(Snapshot),並用這個快照來提供某一層級(語句級或交易級)的一致性讀取。從使用者的角度來看,好像是資料庫可以提供相同資料的多個版本,因此,這種技術叫做資料多版本並發控制(MultiVersion Concurrency Control,簡稱MVCC或MCC),也常稱為多版本資料庫。

資料庫的事務隔離越嚴格,並發副作用越小,但付出的代價也就越大,因為事務隔離實質上就是使事務在一定程度上「串行化」進行,這顯然與「並發」是矛盾的。同時,不同的應用程式對讀取一致性和事務隔離程度的要求也是不同的,例如許多應用程式對「不可重複讀取」和「幻讀」並不敏感,可能更關心資料並發存取的能力。
為了解決「隔離」與「並發」的矛盾,ISO/ANSI SQL92定義了4個事務隔離級別,每個級別的隔離程度不同,允許出現的副作用也不同,應用可以根據自己的業務邏輯要求,透過選擇不同的隔離等級來平衡「隔離」與「並發」的矛盾。表20-5很好地概括了這4個隔離等級的特性。

讀取資料一致性及允許的同時副作用
隔離級別   讀資料一致性 臟讀取 無法重複讀取  幻讀
未提交讀取(Read uncommitted)  最低級別,且只能保證不讀取物理上損壞的資料   是  是  是
已提交度(Read committed)    語句級否  是  是
可重複讀取(Repeatable read)   事務級否    是
可序列化(Repeatable read)   事務級否    是
可序列化(Serializable)最高級別,事務級   否  否  否

###

最後要說明的是:各具體資料庫並不一定完全實現了上述4個隔離級別,例如,Oracle只提供Read committed和Serializable兩個標準隔離級別,另外還提供自己定義的Read only隔離級別; SQL Server除支援上述ISO/ANSI SQL92定義的4個隔離級別外,還支援一個稱為「快照」的隔離級別,但嚴格來說它是一個用MVCC實現的Serializable隔離級別。 MySQL支援全部4個隔離級別,但在具體實現時,有一些特點,例如在一些隔離級別下是採用MVCC一致性讀,但某些情況下又不是
InnoDB有兩種模式的行鎖:
1)共享鎖定(S):允許一個事務去讀一行,阻止其他事務取得相同資料集的排他鎖。
    ( Select * from table_name where ……lock in share mode)
2)排他鎖(X):允許獲得排他鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和排他寫鎖。 (select * from table_name where…..for update)
為了允許行鎖和表鎖共存,實現多粒度鎖機制;同時還有兩種內部使用的意向鎖(都是表鎖),分別為意向共享鎖和意向排他鎖。
1)意圖共享鎖(IS):交易打算為資料行加行共享鎖,交易在給一個資料行加共享鎖前必須先取得該表的IS鎖。
2)意向排他鎖(IX):交易打算為資料行加行排他鎖,交易在給一個資料行加排他鎖前必須先取得該表的IX鎖。
InnoDB行鎖定模式相容性清單
請求鎖定模式
   是否相容
目前鎖定模式  X   IX  S   IS
X   衝突 衝突 衝突 衝突
IX   相容# S   衝突 衝突 相容 相容
IS  衝突 相容 相容 相容
如果一個事務請求的鎖定模式與目前的鎖定相容,InnoDB就將要求的鎖定授予該事務;反之,如果兩者不相容,則該事務就要等待鎖釋放。
意向鎖定是InnoDB自動加的,不需使用者介入。對於UPDATE、DELETE和INSERT語句,InnoDB會自動將涉及資料集加排他鎖(X);對於普通SELECT語句,InnoDB不會加任何鎖定;交易可以透過以下語句顯示給記錄集加上共享鎖定或排他鎖。
1、共享鎖(S):SELECT * FROM table_name WHERE … LOCK IN SHARE MODE。
2、排他鎖(X):SELECT * FROM table_name WHERE … FOR UPDATE。
InnoDB行鎖是透過在索引上的索引項中加鎖來實現的,這一點MySQL與oracle不同,後者是透過在資料區塊中對對應資料行加鎖來實現的。 InnoDB這種行鎖實現特點意味著:只有透過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!
在實際應用中,要特別注意InnoDB行鎖的這項特性,不然的話,可能導致大量的鎖定衝突,進而影響並發效能。

查詢表格層級鎖定爭用情況

表格鎖定爭奪:
可以透過檢查table_locks_waited和table_locks_immediate狀態變數來分析系統上的表格鎖定爭奪:

mysql> show status like ‘table%’; 
+———————–+——-+ 
| Variable_name         | Value | 
+———————–+——-+ 
| Table_locks_immediate | 2979  | 
| Table_locks_waited    | 0     | 
+———————–+——-+ 
2 rows in set (0.00 sec))
登入後複製

如果Table_locks_waited的值比較高,則表示存在較嚴重的表級鎖定爭用情況。

InnoDB行鎖定爭奪:   
可以透過檢查InnoDB_row_lock狀態變數來分析系統上的行鎖定的爭奪情況:

mysql> show status like ‘innodb_row_lock%’; 
+——————————-+——-+ 
| Variable_name                 | Value | 
+——————————-+——-+ 
| InnoDB_row_lock_current_waits | 0     | 
| InnoDB_row_lock_time          | 0     | 
| InnoDB_row_lock_time_avg      | 0     | 
| InnoDB_row_lock_time_max      | 0     | 
| InnoDB_row_lock_waits         | 0     | 
+——————————-+——-+ 
5 rows in set (0.01 sec)
登入後複製

MyISAM寫入鎖定實驗:

對MyISAM表的讀取操作,不會阻塞其他使用者對同一表的讀取請求,但會阻塞對同一表的寫入請求;對MyISAM表的寫入操作,則會阻塞其他使用者對同一表的讀取和寫入操作;MyISAM表的讀操作與寫入操作之間,以及寫入操作之間是串列的!根據如表20-2所示的例子可以知道,當一個執行緒獲得對一個表的寫鎖後,只有持有鎖的執行緒可以對錶進行更新操作。其他執行緒的讀取、寫入操作都會等待,直到鎖被釋放為止。
USER1:

mysql> lock table film_text write;
登入後複製

目前session對鎖定表的查詢、更新、插入操作都可以執行:


mysql> select film_id,title from film_text where film_id = 1001;
登入後複製
登入後複製

USER2:


#

mysql> select film_id,title from film_text where film_id = 1001;
登入後複製
登入後複製

等待

USER1:
釋放鎖定:

mysql> unlock tables;
登入後複製

USER2:

取得鎖定,查詢回傳:
InnoDB儲存引擎的共用鎖定實驗

#

USER1: 
mysql> set autocommit = 0; 
USER2: 
mysql> set autocommit = 0;
登入後複製
登入後複製

USER1:

目前session對actor_id=178的記錄加上share mode 的共享鎖定:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178lock in share mode;
登入後複製
登入後複製

USER2:

其他session仍然可以查詢記錄,也可以對該記錄加share mode的共享鎖定:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178lock in share mode;
登入後複製
登入後複製

USER1:

當前session對鎖定的記錄進行更新操作,等待鎖定:

mysql> update actor set last_name = ‘MONROE T’ where actor_id = 178;
登入後複製
登入後複製
登入後複製

#等待

USER2:
其他session也對此記錄進行更新操作,則會導致死鎖退出:

mysql> update actor set last_name = ‘MONROE T’ where actor_id = 178;
登入後複製
登入後複製
登入後複製

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

USER1:
取得鎖定後,可以成功更新:

mysql> update actor set last_name = ‘MONROE T’ where actor_id = 178; 
Query OK, 1 row affected (17.67 sec) 
Rows matched: 1  Changed: 1  Warnings: 0
登入後複製

InnoDB儲存引擎的排他鎖定範例


USER1: 
mysql> set autocommit = 0; 
USER2: 
mysql> set autocommit = 0;
登入後複製
登入後複製

USER1:
当前session对actor_id=178的记录加for update的排它锁:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;
登入後複製
登入後複製

USER2:
其他session可以查询该记录,但是不能对该记录加共享锁,会等待获得锁:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;
登入後複製

USER1:
当前session可以对锁定的记录进行更新操作,更新后释放锁:

mysql> update actor set last_name = ‘MONROE T’ where actor_id = 178;
登入後複製
登入後複製
登入後複製

USER2:
其他session获得锁,得到其他session提交的记录:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;
登入後複製
登入後複製

更新性能优化的几个重要参数
bulk_insert_buffer_size
批量插入缓存大小,这个参数是针对MyISAM存储引擎来说的.适用于在一次性插入100-1000+条记录时,提高效率.默认值是8M.可以针对数据量的大小,翻倍增加.
concurrent_insert
并发插入,当表没有空洞(删除过记录),在某进程获取读锁的情况下,其他进程可以在表尾部进行插入.
值可以设0不允许并发插入, 1当表没有空洞时,执行并发插入, 2不管是否有空洞都执行并发插入.
默认是1针对表的删除频率来设置.
delay_key_write
针对MyISAM存储引擎,延迟更新索引.意思是说,update记录时,先将数据up到磁盘,但不up索引,将索引存在内存里,当表关闭时,将内存索引,写到磁盘.值为 0不开启, 1开启.默认开启.
delayed_insert_limit, delayed_insert_timeout, delayed_queue_size
延迟插入,将数据先交给内存队列,然后慢慢地插入.但是这些配置,不是所有的存储引擎都支持,目前来看,常用的InnoDB不支持, MyISAM支持.根据实际情况调大,一般默认够用了。


以上是mysql資料庫中鎖機制的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

了解MySQL和PostgreSQL的並發控制和鎖定機制 了解MySQL和PostgreSQL的並發控制和鎖定機制 Jul 13, 2023 pm 09:13 PM

了解MySQL和PostgreSQL的並發控制和鎖定機制引言:在資料庫管理系統(DBMS)中,資料庫並發控制和鎖定機制是至關重要的概念。它們用於管理多個使用者並發存取資料庫時的資料一致性和隔離性。本文將探討MySQL和PostgreSQL兩個常見的關係型資料庫管理系統在並發控制和鎖定機制方面的實作機制,並提供對應的程式碼範例。一、MySQL的同時控制與鎖機制MySQL

Golang中鎖機制的效能優化技巧 Golang中鎖機制的效能優化技巧 Sep 28, 2023 pm 10:33 PM

Golang中鎖機制的效能最佳化技巧,需要具體程式碼範例摘要:Golang是一種高效率的程式語言,廣泛應用於並發程式設計。在多執行緒或分散式環境中,鎖定機制是必不可少的組成部分,但是使用不恰當的鎖定機制可能導致效能下降。本文將介紹幾種Golang中鎖機制的效能最佳化技巧,並提供程式碼範例。關鍵字:Golang、鎖、效能最佳化、程式碼範例介紹鎖定機制是多執行緒或分散式環境中確保資料一

如何使用Java中的鎖機制實現執行緒同步? 如何使用Java中的鎖機制實現執行緒同步? Aug 02, 2023 pm 01:47 PM

如何使用Java中的鎖機制實現執行緒同步?在多執行緒程式設計中,執行緒同步是一個非常重要的概念。當多個執行緒同時存取和修改共享資源時,可能會導致資料不一致或競態條件的問題。 Java提供了鎖定機制來解決這些問題,並確保執行緒安全的存取共享資源。 Java中的鎖定機制由synchronized關鍵字和Lock介面提供。接下來,我們將學習如何使用這兩種機制來實現執行緒同步。使用sync

Go語言中的分散式系統與鎖定機制 Go語言中的分散式系統與鎖定機制 Jun 04, 2023 pm 02:21 PM

隨著互聯網的不斷發展,分散式系統已經成為了應用領域中的熱門話題之一。在分散式系統中,鎖定機制是一個重要的問題,特別是在涉及並發的應用場景中,鎖定機制的效率和正確性越來越受到人們的重視。在這篇文章中,我們將介紹Go語言中的分散式系統和鎖定機制。分散式系統Go語言是一種開源的、現代的程式語言,具有高效、簡潔、易於學習和使用等特點,在工程師團隊中已經得到了廣泛的應用和

如何使用MySQL的鎖定機制處理並發存取衝突 如何使用MySQL的鎖定機制處理並發存取衝突 Aug 02, 2023 am 10:21 AM

如何使用MySQL的鎖定機制處理並發存取衝突在多用戶同時存取資料庫的情況下,可能會出現並發存取衝突的問題。 MySQL提供了鎖定機制用於處理並發存取衝突,本文將介紹如何使用MySQL的鎖定機制來解決這個問題。 MySQL提供了兩種類型的鎖:共用鎖定(SharedLock)和獨佔鎖(ExclusiveLock)。共享鎖可以多個事務同時持有,用於讀取操作;獨佔鎖只能由一

Java 中的鎖機制 Java 中的鎖機制 Jun 08, 2023 am 08:03 AM

Java作為一種高階程式語言,在並發程式設計上有著廣泛的應用。在多執行緒環境下,為了確保資料的正確性和一致性,Java採用了鎖定機制。本文將從鎖的概念、類型、實作方式和使用場景等面向對Java中的鎖機制進行探討。一、鎖的概念鎖是一種同步機制,用來控制多個執行緒之間對共享資源的存取。在多執行緒環境下,執行緒的執行是並發的,多個執行緒可能會同時修改相同數據,這會導致數

Linux系統中常見的資料庫問題及其解決方法 Linux系統中常見的資料庫問題及其解決方法 Jun 18, 2023 pm 03:36 PM

隨著電腦技術的不斷發展和資料規模的不斷增長,資料庫成為了一項至關重要的技術。然而,在Linux系統中使用資料庫還會遇到一些常見的問題,本文將介紹一些常見的Linux系統中的資料庫問題以及它們的解決方法。資料庫連線問題在使用資料庫時,有時會出現連線失敗或連線逾時等問題,造成這些問題的原因可能是資料庫設定錯誤或存取權限不足。解決方法:檢查資料庫的設定文件,確

探索Java多執行緒原理:鎖機制與執行緒安全性 探索Java多執行緒原理:鎖機制與執行緒安全性 Feb 22, 2024 am 10:06 AM

探索Java多執行緒原理:鎖機制與執行緒安全性導言:在軟體開發領域,多執行緒程式設計是一項非常重要的技能。透過使用多線程,我們可以同時執行多個任務,提高程式的效能和響應度。然而,多執行緒程式設計也帶來了一系列的挑戰,其中最重要的就是執行緒安全性。本文將探討Java多執行緒原理,重點在於鎖機制及其在執行緒安全性中的作用。一、什麼是線程安全性?在多執行緒環境下,如果一個操作不會導致任

See all articles