MySQL中的鎖和事務(wù)隔離級(jí)別是什么

MySQL中的鎖和事務(wù)隔離級(jí)別是什么?可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)建站成都網(wǎng)站建設(shè)按需設(shè)計(jì)網(wǎng)站,是成都網(wǎng)站設(shè)計(jì)公司,為酒樓設(shè)計(jì)提供網(wǎng)站建設(shè)服務(wù),有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設(shè)計(jì)服務(wù):原型圖制作、網(wǎng)站創(chuàng)意設(shè)計(jì)、前端HTML5制作、后臺(tái)程序開發(fā)等。成都網(wǎng)站營(yíng)銷推廣熱線:18982081108

數(shù)據(jù)庫的鎖機(jī)制是區(qū)別于文件系統(tǒng)的一個(gè)關(guān)鍵特性。用于管理對(duì)共享資源的并發(fā)訪問。InnoDB會(huì)在很多地方使用鎖機(jī)制,比如操作緩沖池中的數(shù)據(jù)表、LRU頁列表、數(shù)據(jù)行,為了保證一致性和完整性,需要有鎖的機(jī)制。

對(duì)于不同數(shù)據(jù)庫,鎖機(jī)制的設(shè)計(jì)和實(shí)現(xiàn)完全不同:

● MyISAM引擎: 表鎖設(shè)計(jì),并發(fā)讀沒有問題,并發(fā)寫性能差。

● Microsoft SQL Server: 支持樂觀并發(fā)和悲觀并發(fā),樂觀并發(fā)下支持行級(jí)鎖,維持鎖的開銷大,在行鎖數(shù)量超過閾值后會(huì)升級(jí)為表鎖。

● InnoDB引擎: 支持行鎖,提供一致性的非鎖定讀。行鎖沒有額外開銷,性能不會(huì)下降。

● Oracle:和InnoDB引擎非常類似。

兩類鎖:lock和latch

數(shù)據(jù)庫中l(wèi)ock和latch都可以稱為鎖,但是有很大的區(qū)別。

latch一般稱為閂鎖,用于保證并發(fā)線程操作臨界資源的正確性,作用對(duì)象是內(nèi)存數(shù)據(jù)結(jié)構(gòu),要求鎖定時(shí)間非常短,不會(huì)檢測(cè)死鎖。在InnoDB引擎中又分為mutex(互斥量)和rwlock(讀寫鎖)。

lock是用來鎖定數(shù)據(jù)庫中的對(duì)象,如表、頁、行,作用對(duì)象是事務(wù),在commit/rollback后釋放,會(huì)檢測(cè)死鎖。分為行鎖、表鎖、意向鎖。

我們下面的鎖指的都是lock類鎖。

四種鎖類型

InnoDB支持四種鎖:

● 共享鎖(S Lock):允許事務(wù)讀一行數(shù)據(jù)

● 排他鎖(X Lock):允許事務(wù)刪除或更新一行數(shù)據(jù)

● 意向共享鎖(Intention S Lock):事務(wù)想要獲得一張表中某幾行的共享鎖

● 意向排他鎖(Intention X Lock):事務(wù)想要獲得一張表中某幾行的排他鎖

當(dāng)事務(wù)T1獲取了行r的共享鎖,由于讀取不會(huì)改變行數(shù)據(jù),因此事務(wù)T2也可以直接獲得行r的共享鎖,此時(shí)稱為鎖兼容(Lock Compatible)。

而當(dāng)事務(wù)T3想要獲取行r的排他鎖進(jìn)行修改數(shù)據(jù)時(shí),就需要等待T1/T2釋放行共享鎖,此時(shí)稱為鎖不兼容。

S鎖和X鎖都是行鎖,而IS鎖和IX鎖都為意向鎖,屬于表鎖。意向鎖的設(shè)計(jì)是為了在一個(gè)事務(wù)中揭示下一行將被請(qǐng)求的鎖類型,即在表鎖的更細(xì)粒度進(jìn)行鎖定。由于InnoDB支持表鎖,因此意向鎖不會(huì)阻塞除全表掃描外的任何請(qǐng)求。

鎖的兼容性:


ISIXSX
IS兼容兼容兼容不兼容
IX兼容兼容不兼容不兼容
S兼容不兼容兼容不兼容
X不兼容不兼容不兼容不兼容

存儲(chǔ)事務(wù)和鎖信息的三張表

我們可以通過show engine innodb status命令在事務(wù)部分查看當(dāng)前鎖請(qǐng)求的信息。

從InnoDB1.0開始,在INFORMATION_SCHEMA架構(gòu)下添加了INNODB_TRX(transaction事務(wù)表)、INNODB_LOCKS(鎖表)、INNODB_LOCK_WAITS(鎖等待表),通過這三張表,可以讓我們實(shí)時(shí)監(jiān)控當(dāng)前事務(wù)并分析可能存在的表問題。

三個(gè)表的定義分別為:

INNODB_TRX
trx_idInnoDB存儲(chǔ)引擎內(nèi)部唯一的事務(wù)ID
trx_state當(dāng)前事務(wù)的狀態(tài)
trx_started事務(wù)的開始時(shí)間
trx_requested_lock_id等待事務(wù)的鎖IDC,當(dāng)狀態(tài)不為L(zhǎng)OCK WAIT時(shí)為NULL
trx_wait_started事務(wù)等待開始的時(shí)間
trx_weight事務(wù)的權(quán)重,反映一個(gè)事務(wù)修改和鎖定的行數(shù)。當(dāng)需要回滾時(shí),選擇該值最小的事務(wù)進(jìn)行回滾
trx_mysql_thread_idMySQL的線程ID,show processlist顯示的結(jié)果
trx_query事務(wù)運(yùn)行的SQL語句
INNODB_LOCKS
lock_id鎖ID
lock_trx_id事務(wù)ID
lock_mode鎖的模式
lock_type鎖的類型,表鎖或行鎖
lock_table要加鎖的表
lock_index鎖住的索引
lock_space鎖對(duì)象的space id
lock_page事務(wù)鎖定頁的數(shù)量,表鎖時(shí)為NULL
lock_rec事務(wù)鎖定行的數(shù)量,表鎖時(shí)為NULL
lock_data事務(wù)鎖定記錄的主鍵值,表鎖時(shí)為NULL
INNODB_LOCK_WAITS
requesting_trx_id申請(qǐng)鎖資源的事務(wù)ID
requesting_lock_id申請(qǐng)的鎖的ID
blocking_trx_id阻塞的事務(wù)ID
blocking_lock_id阻塞的鎖的ID

通過INNODB_TRX我們可以看到所有的事務(wù),以及事務(wù)是否被阻塞,阻塞的鎖ID是什么。
之后,通過INNODB_LOCKS查看所有的鎖信息。
之后,通過INNODB_LOCK_WAITS可以查看到鎖的等待信息以及阻塞關(guān)系。

通過這三種表能夠較為清晰的查看事務(wù)和鎖的情況,也可以聯(lián)合查詢,在下面的一些場(chǎng)景下我們會(huì)來展示這三個(gè)表的內(nèi)容。

隔離級(jí)別

首先我們來說下數(shù)據(jù)庫的四種事務(wù)隔離級(jí)別:

● READ UNCOMMITTED(0): 瀏覽訪問級(jí)別,存在臟讀、不可重復(fù)讀、幻讀

● READ COMMITTED(1): 游標(biāo)穩(wěn)定級(jí)別,存在不可重復(fù)度、幻讀

● REPEATABLE READ(2): 存在幻讀

● SERIALIZABLE(3): 隔離級(jí)別,保證事務(wù)安全,但完全串行,性能低

這四種事務(wù)隔離級(jí)別是指定的SQL標(biāo)準(zhǔn),InnoDB默認(rèn)的隔離級(jí)別是REAPEATABLE READ,但與其他數(shù)據(jù)庫不同的時(shí),它同時(shí)使用了Next-Key-Lock鎖的算法,能夠避免幻讀的產(chǎn)生,因此能夠完全滿足事務(wù)的隔離性要求,即達(dá)到SERIALIZABLE隔離級(jí)別。

隔離級(jí)別越低,事務(wù)請(qǐng)求的鎖越少或持鎖時(shí)間越短,因此大部分?jǐn)?shù)據(jù)庫的默認(rèn)隔離級(jí)別為READ COMMITED。但是有相關(guān)的分析也指出,隔離級(jí)別的性能開銷幾乎一樣,因此用戶無須通過調(diào)整隔離級(jí)別來提高性能。

查看和修改事務(wù)隔離級(jí)別的命令:

mysql> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ        |
+------------------------+
1 row in set (0.00 sec)

mysql> set session transaction isolation level SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)

示例中修改了本次會(huì)話的事務(wù)隔離級(jí)別,如果需要修改全局參數(shù),可以替換session為global。如果想要永久修改,需要修改配置文件:

[mysqld]
transaction-isolation = READ-COMMITED

在SERIALIZABLE的事務(wù)隔離級(jí)別,InnoDB會(huì)對(duì)每個(gè)SELECT語句后自動(dòng)加上LOCK IN SHARE MODE,來對(duì)讀操作加上一個(gè)共享鎖,因此不再支持一致性的非鎖定讀。

由于InnoDB在REPEATABLE READ隔離級(jí)別就可以達(dá)到SERIALIZABLE,因此一般不用使用最高隔離級(jí)別。

一致性非鎖定讀和多版本并發(fā)控制

一致性非鎖定讀(consistent nonlocking read)是指InnoDB通過行多版本控制(Multi Version Concurrency Control, MVCC)的方法來讀取當(dāng)前執(zhí)行時(shí)間數(shù)據(jù)庫中行的數(shù)據(jù)。

即如果讀取的行正在執(zhí)行變更操作,這時(shí)讀取不會(huì)等待行鎖的釋放,而是會(huì)讀取行的一個(gè)快照數(shù)據(jù)??煺帐侵冈撔械囊粋€(gè)歷史數(shù)據(jù),通過undo操作來完成。這種方式極大提高了數(shù)據(jù)庫的并發(fā)性,這也是InnoDB的默認(rèn)設(shè)置。

快照是當(dāng)前行的一個(gè)歷史版本,但可能存在多個(gè)版本,行數(shù)據(jù)存在多個(gè)快照數(shù)據(jù),這種技術(shù)成為行多版本技術(shù),由此帶來的并發(fā)控制,稱為多版本并發(fā)控制(MVCC)。InnoDB在READ COMMITED 和 REPEATABLE READ隔離級(jí)別時(shí),會(huì)使用非鎖定的一致性讀,但是在這兩種隔離級(jí)別使用的快找數(shù)據(jù)定義卻不同:

● READ COMMITED: 總是讀取最新一份快照

● REPEATABLE READ: 總是讀取事務(wù)開始時(shí)的行數(shù)據(jù)版本

我們執(zhí)行一個(gè)示例:

一致性非鎖定讀
時(shí)間會(huì)話A會(huì)話B
1BEGIN
2select * from z where a = 3;
3
BEGIN
4
update z set b=2 where a=3;
5select * from z where a = 3;
6
COMMIT;
7select * from z where a = 3;
8COMMIT;

在這個(gè)例子中我們可以清晰的看到0、1、2三種隔離級(jí)別的區(qū)別:

#在事務(wù)開始前我們可以分別調(diào)整為0、1、2三種隔離級(jí)別,來查看不同的輸出
mysql> set session transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

# A會(huì)話:T1事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from z where a = 3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# B會(huì)話:T2事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update z set b=2 where a=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# A會(huì)話:T1事務(wù),如果此時(shí)隔離級(jí)別是READ-UNCOMMITTED,因?yàn)榇丝淌聞?wù)2可能會(huì)回滾,所以出現(xiàn)了臟讀
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    2 |
+---+------+
1 row in set (0.00 sec)

# A會(huì)話:T1事務(wù),如果此時(shí)隔離級(jí)別是大于READ-UNCOMMITTED的更高級(jí)別
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# B會(huì)話:T2事務(wù)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

# A會(huì)話:T1事務(wù),如果此時(shí)隔離級(jí)別是READ-COMMITTED,因?yàn)閿?shù)據(jù)和事務(wù)開始時(shí)讀取的出現(xiàn)了不一致,因此稱為不可重復(fù)讀,能夠讀到其他事務(wù)的結(jié)果,違反了事務(wù)的隔離性
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    2 |
+---+------+
1 row in set (0.00 sec)

# A會(huì)話:T1事務(wù),如果此時(shí)隔離級(jí)別是大于READ-COMMITTED的更高級(jí)別
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# A會(huì)話:T1事務(wù)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

一致性鎖定讀和SERIALIZABLE隔離

在默認(rèn)的REPEATABLE READ隔離級(jí)別時(shí),InnoDB使用的是一致性非鎖定讀。但有時(shí)我們也需要顯示的指定使用一致性鎖定讀來保證讀取操作時(shí)對(duì)數(shù)據(jù)進(jìn)行加鎖達(dá)到一致性。這要求數(shù)據(jù)庫支持鎖定讀加鎖語句:

● select ... for update: 讀取時(shí)對(duì)行記錄加X鎖

● select ... lock in share mode:讀取時(shí)對(duì)行記錄加一個(gè)S鎖

這兩種鎖必須在一個(gè)事務(wù)中,當(dāng)事務(wù)提交后鎖也就釋放了,因此務(wù)必加上BEGIN, START TRANSACTION或者SET AUTOCOMMIT=0。

我們?cè)谇懊娓綦x級(jí)別時(shí)也說過SERIALIZABLE隔離級(jí)別會(huì)對(duì)讀操作自動(dòng)加上LOCK IN SHARE MODE指令來加上一個(gè)共享鎖,因此不再支持一致性的非鎖定讀。這也是隔離級(jí)別3的一大特性。

總結(jié)

由于鎖的概念非常重要,這里先講了鎖的概念、鎖的類型、鎖的信息查看、事務(wù)的隔離級(jí)別和區(qū)別,后面我們會(huì)繼續(xù)說鎖的算法、鎖的三種問題和幻讀、死鎖和鎖升級(jí)。

看完上述內(nèi)容,你們對(duì)MySQL中的鎖和事務(wù)隔離級(jí)別有進(jìn)一步的了解嗎?如果還想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀。

分享標(biāo)題:MySQL中的鎖和事務(wù)隔離級(jí)別是什么
鏈接分享:http://bm7419.com/article26/jcscjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、品牌網(wǎng)站制作、商城網(wǎng)站、Google、網(wǎng)站策劃、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作