日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql lock_MySQL-锁总结

發(fā)布時(shí)間:2024/7/23 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql lock_MySQL-锁总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鎖機(jī)制用于管理對共享資源的并發(fā)訪問。

lock和latch

在數(shù)據(jù)庫中,lock和Latch都稱為鎖,但是兩者意義不同。

latch稱為閂鎖(shuang suo),其要求鎖定的時(shí)間必須非常短。若持續(xù)的時(shí)間長,則應(yīng)用的性能會非常差。在InnoDB存儲引擎中,latch又分為mutex互斥鎖 和 rwLock讀寫鎖。其目的是為了保證并發(fā)線程操作臨界資源的正確性。通常沒有死鎖的檢測機(jī)制。

lock的對象是事務(wù),用來鎖定的是數(shù)據(jù)庫中的對象,如表、頁、行。并且一般lock的對象僅在事務(wù)commit或者rollback后進(jìn)行釋放。有死鎖檢測機(jī)制。

通過show engine innodb mutex可以查看InnoDB存儲引擎的中l(wèi)atch,具體字段詳情如下表:

鎖的類型

有幾個(gè)索引,需要分別向索引加鎖。

共享鎖、排他鎖

InnoDB存儲引擎實(shí)現(xiàn)了如下兩種標(biāo)準(zhǔn)的行級鎖:

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

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

如果一個(gè)事務(wù)T1已經(jīng)獲取了行r的共享鎖,那么另外的事務(wù)T2可以立即獲得行r的共享鎖。因?yàn)樽x取并不會改變行的數(shù)據(jù),所以可以多個(gè)事務(wù)同時(shí)獲取共享鎖,稱這種情況為鎖兼容。但若有其他的事務(wù)T3想獲得行R的排他鎖,則其必須等待事務(wù)T1、T2釋放行r上面的共享鎖,稱這種情況為鎖不兼容。下面顯示了共享鎖和排他鎖的兼容性:

從表6-3可以看出X鎖與任何鎖都不兼容,而S鎖僅和S鎖兼容。S鎖和X鎖都是行鎖,兼容是指對同一行記錄鎖的兼容情況。

普通 select 語句默認(rèn)不加鎖,而CUD操作默認(rèn)加排他鎖。

記錄鎖

Record Lock,僅鎖定一行記錄(如共享鎖、排他鎖)

記錄鎖總是會去鎖定索引記錄,如果表在建立的時(shí)候,沒有設(shè)置任何一個(gè)索引,那么InnoDB會使用隱式的主鍵來進(jìn)行鎖定。

查詢條件的列是唯一索引的情況下,臨建鎖退化為記錄鎖

間隙鎖

Gap Lock,鎖定一個(gè)范圍,但不包含記錄本身。

關(guān)閉間隙鎖的2種方式:

(1)將事務(wù)隔離級別變?yōu)閞ead committed

(2)將參數(shù)innodb_locks_unsafe_for_binlog設(shè)置為1

在上述配置下,除了外鍵和唯一性檢查依然需要間隙鎖,其余情況僅適用行鎖進(jìn)行鎖定。

臨鍵鎖

Next-Key Lock,等于記錄鎖 + 臨鍵鎖,鎖定一個(gè)范圍,并且鎖定記錄本身。主要是阻止多個(gè)事務(wù)將記錄插入到同一個(gè)范圍內(nèi),從而避免幻讀。

假如一個(gè)索引有10、11、13、20這四個(gè)值,那么該索引可能被鎖定的區(qū)間為:

若事務(wù)T1已經(jīng)通過臨鍵鎖鎖定了如下范圍:

當(dāng)插入新的記錄12時(shí),則鎖定的范圍變成:

當(dāng)查詢的索引是唯一索引的時(shí)候,InnoDB會將臨鍵鎖優(yōu)化成記錄鎖,從而提高并發(fā)。這時(shí)候,將不再由間隙鎖避免幻讀的問題,但是試驗(yàn)了下,即使優(yōu)化成記錄鎖,也不會有幻讀的問題,其實(shí)是因?yàn)镸VCC,在可重復(fù)讀的情況下,SELECT操作只會查找行版本號小于當(dāng)前事務(wù)版本號的記錄,其他事務(wù)(事務(wù)開啟時(shí)間比當(dāng)前事務(wù)晚)新插入的記錄版本號不滿足條件,就不會查出來。

對于輔助索引,當(dāng)執(zhí)行類似select * from z where b = 3 for update;加鎖語句時(shí),會加上臨鍵鎖,并且下一個(gè)鍵值的范圍也會加上間隙鎖。

值得注意的是,對于唯一鍵值的鎖定,由臨鍵鎖優(yōu)化為記錄鎖,僅存在于查詢所有的唯一索引。若唯一索引由多列組成,而查詢僅是查找多個(gè)唯一索引中的一個(gè),那么查詢其實(shí)是range類型查詢,而不是point類型查詢,故InnoDB存儲引擎還是繼續(xù)使用臨鍵鎖。

在InnoDB存儲引擎中,通過使用臨鍵鎖來避免不可重復(fù)讀的問題(即幻讀)。在使用臨鍵鎖的情況下,對于索引的掃描,不僅僅鎖住掃描的到索引,而且還鎖住這些索引覆蓋的范圍。因此,在這些范圍內(nèi)插入都是不允許的。這樣子就避免了其他事務(wù)在這些范圍內(nèi)插入數(shù)據(jù)導(dǎo)致不可重復(fù)讀的問題。

意向鎖

概念:未來的某個(gè)時(shí)刻,事務(wù)可能要加共享/排它鎖了,先提前聲明一個(gè)意向

意向鎖有這樣一些特點(diǎn):

(1)意向鎖是表級別的鎖

(2)意向鎖分為:

意向共享鎖(intention shared lock, IS),它預(yù)示著,事務(wù)有意向?qū)Ρ碇械哪承┬屑庸蚕鞸鎖

意向排它鎖(intention exclusive lock, IX),它預(yù)示著,事務(wù)有意向?qū)Ρ碇械哪承┬屑优潘黊鎖

(3)意向鎖協(xié)議:

事務(wù)要獲得某些行的共享鎖,必須先獲得表的意向共享鎖IS

事務(wù)要獲取某些行的排他鎖,必須先獲得表的意向排他鎖IX

(4)由于意向鎖僅僅表明意向,它其實(shí)是比較弱的鎖,意向鎖之間并不相互互斥,而是可以并行,其兼容互斥表如下:

? IS IX

IS 兼容 兼容

IX 兼容 兼容

(5)既然意向鎖之間都相互兼容,那其意義在哪里呢?它會與共享鎖/排它鎖互斥,其兼容互斥表如下:

? S X

IS 兼容 互斥

IX 互斥 互斥

(排它鎖是很強(qiáng)的鎖,不與其他類型的鎖兼容。這也很好理解,修改和刪除某一行的時(shí)候,必須獲得強(qiáng)鎖,禁止這一行上的其他并發(fā),以保障數(shù)據(jù)的一致性。)

InnoDB支持多粒度鎖定,這種鎖定允許事務(wù)在行級上的鎖和表級上的鎖同時(shí)存在。為了支持不同粒度上進(jìn)行加鎖操作,InnoDB存儲引擎支持一種額外的鎖方式,稱之為意向鎖。意向鎖是將鎖定的對象分為多個(gè)層次,意向鎖意味著事務(wù)希望在更細(xì)的粒度上進(jìn)行加鎖。如圖6-3所示:

若將上鎖的對象看成一棵樹,那么對最下層的對象上鎖,也就是對最細(xì)粒度的對象上鎖,那么首先需要對粗粒度的對象進(jìn)行上鎖。如上圖,如果需要對頁上的記錄上X鎖,那么需要分別對數(shù)據(jù)庫A、表、頁 上意向鎖IX,最后對記錄r上排他鎖X。

若其中任何一部分導(dǎo)致等待,那么該操作需要等待粗粒度鎖的完成。舉例來說,事務(wù)T1在對記錄r加X鎖之前,已有事務(wù)T2對表1進(jìn)行了S表鎖,那么表1上面已經(jīng)存在S鎖,之后事務(wù)T1試圖在表1上加IX鎖(獲取記錄r的X鎖必須先獲取表1的IX鎖),由于不兼容,所以事務(wù)T1需要等待事務(wù)T2釋放表鎖。

插入意向鎖

對已有數(shù)據(jù)行的修改與刪除,必須加強(qiáng)互斥鎖X鎖,那對于數(shù)據(jù)的插入,是否還需要加這么強(qiáng)的鎖,來實(shí)施互斥呢?插入意向鎖,孕育而生。

插入意向鎖,是間隙鎖(Gap Locks)的一種(所以,也是實(shí)施在索引上的),它是專門針對insert操作的。

它的用處是:多個(gè)事務(wù),在同一個(gè)索引,同一個(gè)范圍區(qū)間插入記錄時(shí),如果插入的位置不沖突,不會阻塞彼此。

示例

在MySQL,InnoDB,RR下:

t(id unique PK, name);

數(shù)據(jù)表中有數(shù)據(jù):

10, shenjian

20, zhangsan

30, lisi

事務(wù)A先執(zhí)行,在10與20兩條記錄中插入了一行,還未提交:

insert into t values(11, xxx);

事務(wù)B后執(zhí)行,也在10與20兩條記錄中插入了一行:

insert into t values(12, ooo);

(1)會使用什么鎖?

(2)事務(wù)B會不會被阻塞呢?

回答:雖然事務(wù)隔離級別是RR,雖然是同一個(gè)索引,雖然是同一個(gè)區(qū)間,但插入的記錄并不沖突,故這里:

使用的是插入意向鎖

并不會阻塞事務(wù)B

自增鎖

自增鎖是MySQL一種特殊的鎖,如果表中存在自增字段,MySQL便會自動維護(hù)一個(gè)自增鎖。

在InnoDB存儲引擎的內(nèi)存結(jié)構(gòu)中,對每個(gè)含有自增長值的表都有一個(gè)自增長計(jì)數(shù)器。當(dāng)對含有自增長計(jì)數(shù)器的表進(jìn)行插入操作時(shí),這個(gè)這個(gè)計(jì)數(shù)器會被初始化,執(zhí)行如下操作來得到計(jì)數(shù)器的值:

select max(auto_inc_col) from t for update

插入操作會依據(jù)這個(gè)自增長的計(jì)數(shù)器值加1賦予自增長列。這個(gè)實(shí)現(xiàn)方式成為Auto-Inc Locking。這種鎖其實(shí)是采用一種表鎖的機(jī)制,為了提高插入的性能,鎖不是在一個(gè)事務(wù)完成以后才釋放,而是在完成對自增長值插入的SQL語句后立即釋放。

雖然Auto-Inc Locking從一定程度上提高了并發(fā)插入的效率,但還是存在一些性能上的問題。對于有自增長值的列的并發(fā)插入性能較差,事務(wù)必須等待前一個(gè)插入的完成(雖然不用等待事務(wù)的完成)。

從MySQL5.12版本開始,InnoDB存儲引擎提供了一種輕量級互斥量的自增長實(shí)現(xiàn)方式。這種方式大大提高了自增長值插入的性能。并且從該版本開始,InnoDB存儲引起提供了一個(gè)參數(shù)innodb_innodb_autoinc_lock_mode來控制自增長模式,該參數(shù)的默認(rèn)值為1。首先看下自增長的插入分類,如下圖:

下圖展示了innodb_innodb_autoinc_lock_mode的不同值對自增的影響:(值為1、2的時(shí)候,看不懂。。)

InnoDB存儲引擎中自增長的實(shí)現(xiàn)和MyISAM不同。MyISAM存儲引擎是表鎖設(shè)計(jì),自增長不用考慮并發(fā)插入的問題。在InnoDB存儲引擎中,自增長值的列必須是索引,同時(shí)必須是索引的第一個(gè)列,如果不是第一個(gè)列,則MySQL會拋出異常。MyISAM存儲引擎沒有這個(gè)問題。

外鍵與鎖

如果沒有為外鍵顯示添加索引,InnoDB自動為外鍵創(chuàng)建索引,這樣子避免表鎖。

對于外鍵值的插入或更新,首先需要查詢父表中的記錄,即select父表。但是不是使用一致性非鎖定讀,因?yàn)檫@樣子會發(fā)生數(shù)據(jù)不一致的問題。因此這時(shí)使用的是select…lock in share mode,即主動對父表加一個(gè)共享鎖。如果這時(shí)父表已經(jīng)加了X鎖,子表上面的操作將會被阻塞,如下圖:

MVCC多版本

又稱為一致性非鎖定讀。指InnoDB通過行多版本控制的方式來讀取當(dāng)前執(zhí)行時(shí)間數(shù)據(jù)庫中行的數(shù)據(jù)。如果讀取的行正在執(zhí)行delete或者update操作,這時(shí)讀操作不會因此去等待行上鎖的釋放。相反的,InnoDB存儲引擎會去讀取行的一個(gè)快照數(shù)據(jù)。

在默認(rèn)配置下,即事務(wù)的隔離界別為REPEATABLE READ(可重復(fù)讀)模式下,InnoDB存儲引擎的SELECT操作使用一致性非鎖定讀。

快照數(shù)據(jù)是指該行的之前版本的數(shù)據(jù),該實(shí)現(xiàn)是通過undo段來完成。而undo用來在事務(wù)中回滾數(shù)據(jù),因此快照數(shù)據(jù)本身是沒有額外的開銷。此外讀取快照數(shù)據(jù)是不需要上鎖的,因?yàn)闆]有事務(wù)需要對歷史的數(shù)據(jù)進(jìn)行修改操作。

非鎖定度機(jī)制極大的提高了數(shù)據(jù)庫的并發(fā)性。這是InnoDB默認(rèn)的讀取方式,即讀取不會占用表上的鎖。但是在不同事務(wù)隔離界別下,讀取的方式不同,并不是在每個(gè)事務(wù)隔離界別下都是采用非鎖定的一致性讀。此外,即使都是使用非鎖定的一致性讀,但是對于快照數(shù)據(jù)的定義也是各不相同。

快照數(shù)據(jù)其實(shí)就是當(dāng)前行數(shù)據(jù)之前的歷史版本,每行記錄可能有多個(gè)版本。一個(gè)行記錄可能有不止一個(gè)快照數(shù)據(jù),一般稱這種技術(shù)為行多版本技術(shù),由此帶來的并發(fā)控制,稱之為多版本并發(fā)控制 MVCC。

在事務(wù)隔離界別read committed 和 repeatable read(InnoDB默認(rèn)的事務(wù)隔離界別)下,InnoDB使用非鎖定一致性讀。然而,對于快照數(shù)據(jù)的定義卻不相同。對于快照數(shù)據(jù),非一致性讀總是讀取被鎖定行的最新一份快照數(shù)據(jù)(如果沒有被鎖定,則讀取行的最新數(shù)據(jù);如果行鎖定了,則讀取該行的最新一個(gè)快照)。而在repeatable read事務(wù)隔離級別下,對于快照數(shù)據(jù),非一致性讀總是讀取事務(wù)開始時(shí)的行數(shù)據(jù)版本。

MVCC的優(yōu)缺點(diǎn)

MVCC在大多數(shù)情況下代替了行鎖,實(shí)現(xiàn)了對讀的非阻塞,讀不加鎖,讀寫不沖突。缺點(diǎn)是每行記錄都需要額外的存儲空間,需要做更多的行維護(hù)和檢查工作。注意寫寫不能并行。

MVCC的實(shí)現(xiàn)原理

undo log

undo log是為回滾而用,具體內(nèi)容就是copy事務(wù)前的數(shù)據(jù)庫內(nèi)容(行)到undo buffer,在適合的時(shí)間把undo buffer中的內(nèi)容刷新到磁盤。undo buffer與redo buffer一樣,也是環(huán)形緩沖,但當(dāng)緩沖滿的時(shí)候,undo buffer中的內(nèi)容會也會被刷新到磁盤;與redo log不同的是,磁盤上不存在單獨(dú)的undo log文件,所有的undo log均存放在主ibd數(shù)據(jù)文件中(表空間),即使客戶端設(shè)置了每表一個(gè)數(shù)據(jù)文件也是如此。在Innodb中,undo log被劃分為多個(gè)段,具體某行的undo log就保存在某個(gè)段中,稱為回滾段。可以認(rèn)為undo log和回滾段是同一意思。

為了便于理解MVCC的實(shí)現(xiàn)原理,這里簡單介紹一下undo log的工作過程

在不考慮redo log 的情況下利用undo log工作的簡化過程為:

序號 動作

1 開始事務(wù)

2 記錄數(shù)據(jù)行數(shù)據(jù)備份到undo log

3 更新數(shù)據(jù)

4 將undo log寫到磁盤

5 將數(shù)據(jù)寫到磁盤

6 提交事務(wù)

(1)為了保證數(shù)據(jù)的持久性,數(shù)據(jù)要在事務(wù)提交之前持久化

(2)undo log的持久化必須在在數(shù)據(jù)持久化之前,這樣才能保證系統(tǒng)崩潰時(shí),可以用undo log來回滾事務(wù)

(3)Innodb通過undo log保存了已更改行的舊版本的快照。

redo log

redo log就是保存執(zhí)行的SQL語句到一個(gè)指定的Log文件,當(dāng)MySQL執(zhí)行recovery(修復(fù))時(shí)重新執(zhí)行redo log記錄的SQL操作即可。當(dāng)客戶端執(zhí)行每條SQL(更新語句)時(shí),redo log會被首先寫入log buffer;當(dāng)客戶端執(zhí)行COMMIT命令時(shí),log buffer中的內(nèi)容會被視情況刷新到磁盤。redo log在磁盤上作為一個(gè)獨(dú)立的文件存在,即Innodb的log文件。

Innodb中的隱藏列

InnoDB的內(nèi)部實(shí)現(xiàn)中為每一行數(shù)據(jù)增加了三個(gè)隱藏列用于實(shí)現(xiàn)MVCC。

列名

長度(字節(jié))

作用

DB_TRX_ID

6

插入或更新行的最后一個(gè)事務(wù)的事務(wù)標(biāo)識符。(刪除視為更新,將其標(biāo)記為已刪除)

DB_ROLL_PTR

7

寫入回滾段的撤消日志記錄(若行已更新,則撤消日志記錄包含在更新行之前重建行內(nèi)容所需的信息)

DB_ROW_ID

6

行標(biāo)識(隱藏單調(diào)自增id)

一行記錄的結(jié)構(gòu)如下:

數(shù)據(jù)列

..

DB_ROW_ID

DB_TRX_ID

DB_ROLL_PTR

MVCC工作過程

MVCC只在READ COMMITED 和 REPEATABLE READ 兩個(gè)隔離級別下工作。READ UNCOMMITTED總是讀取最新的數(shù)據(jù)行,而不是符合當(dāng)前事務(wù)版本的數(shù)據(jù)行。而SERIALIZABLE 則會對所有讀取的行都加鎖。另外事務(wù)的版本號是遞增的。

SELECT

InnoDB 會根據(jù)兩個(gè)條件來檢查每行記錄:

InnoDB只查找版本(DB_TRX_ID)早于當(dāng)前事務(wù)版本的數(shù)據(jù)行(行的系統(tǒng)版本號<=事務(wù)的系統(tǒng)版本號,這樣可以確保數(shù)據(jù)行要么是在開始之前已經(jīng)存在了,要么是事務(wù)自身插入或修改過的)

行的刪除版本號(DB_ROLL_PTR)要么未定義(未更新過),要么大于當(dāng)前事務(wù)版本號(在當(dāng)前事務(wù)開始之后更新的)。這樣可以確保事務(wù)讀取到的行,在事務(wù)開始之前未被刪除。

INSERT

InnoDB為新插入的每一行保存當(dāng)前系統(tǒng)版本號作為行版本號

DELETE

InnoDB為刪除的每一行保存當(dāng)前的系統(tǒng)版本號作為行刪除標(biāo)識

UPDATE

innodb為插入一行新紀(jì)錄,保存當(dāng)前系統(tǒng)版本號作為行版本號,同時(shí)保存當(dāng)前系統(tǒng)版本號到原來的行作為行刪除標(biāo)示。

MVCC插入示例

F1~F6是字段名稱,1~6是對應(yīng)的數(shù)據(jù)。后面3個(gè)隱藏字段分別對應(yīng)行ID、事務(wù)ID、回滾指針。

初始狀態(tài)

假如有一條新增的數(shù)據(jù),可以認(rèn)為行ID為1,其他兩個(gè)字段為空。

事務(wù)1更改該行的值

當(dāng)事務(wù)1更改該行的值時(shí),會進(jìn)行如下操作:

用排他鎖鎖定該行

記錄redo log

把該行修改前的值復(fù)制到undo log,即上圖中下面的行

修改當(dāng)前的行的值,填寫事務(wù)編號,使回滾指針指向undo log中修改的行

釋放鎖

事務(wù)2更改該行的值

與事務(wù)1相同,此時(shí)undo log中有2條記錄,并且通過回滾指針連在一起。

因此,如果undo log一直不刪除,則可以通過當(dāng)前記錄的回滾指針回溯到該行創(chuàng)建時(shí)的初始內(nèi)容,所幸的是在InnoDB中存在清理線程,它會查詢比現(xiàn)在最老的事務(wù)還早的undo log,并刪除它們,從而保證undo log文件不會無限增長。

事務(wù)提交

當(dāng)事務(wù)正常提交時(shí),InnoDB只需要更改事務(wù)狀態(tài)為COMMIT即可,不需要做其他額外的工作,而回滾則復(fù)雜一點(diǎn),需要根據(jù)回滾指針找出事務(wù)修改前的版本,并且恢復(fù)。如果事務(wù)影響的行非常多,回滾則可能變得效率不高。

一致性非鎖定讀(見共享鎖、排他鎖)

在某些情況下,用戶需要顯式的對數(shù)據(jù)庫讀取操作進(jìn)行加鎖以保證數(shù)據(jù)邏輯的一致性。而這要求數(shù)據(jù)庫支持加鎖語句。InnoDB存儲引擎對于SELECT語句支持兩種一致性的鎖定度操作:

select … for update

共享鎖(S鎖, share locks)。其他事務(wù)可以讀取數(shù)據(jù),但不能對該數(shù)據(jù)進(jìn)行修改,直到所有的共享鎖被釋放。

? 如果事務(wù)對某行數(shù)據(jù)加上共享鎖之后,可進(jìn)行讀寫操作;其他事務(wù)可以對該數(shù)據(jù)加共享鎖,但不能加排他鎖,且只能讀數(shù)據(jù),不能修改數(shù)據(jù)。

select … lock in share mode

? 如果事務(wù)對數(shù)據(jù)加上排他鎖之后,則其他事務(wù)不能對該數(shù)據(jù)加任何的鎖。獲取排他鎖的事務(wù)既能讀取數(shù)據(jù),也能修改數(shù)據(jù)。

select…for update對讀取的行記錄加一個(gè)X鎖,其他事務(wù)不能對已鎖定的行加上任何鎖。select…lock in share mode對讀取的行記錄加一個(gè)S鎖,其他事務(wù)可以向被鎖定的行加S鎖,但是如果加X鎖,則會被阻塞。

對于一致性非鎖定讀,即時(shí)讀取的行已經(jīng)被執(zhí)行了select..for update,也是可以進(jìn)行讀取的。

如果不加篩選條件(或者篩選條件不走索引),會升級為表鎖

索引數(shù)據(jù)重復(fù)率太高會導(dǎo)致全表掃描:當(dāng)表中索引字段數(shù)據(jù)重復(fù)率太高,則MySQL可能會忽略索引,進(jìn)行全表掃描,此時(shí)使用表鎖。可使用 force index 強(qiáng)制使用索引。

鎖問題

臟讀

臟數(shù)據(jù):指的是事務(wù)對緩沖池中行記錄的修改,并且還沒有提交。即事務(wù)未提交的數(shù)據(jù)。

臟讀:指當(dāng)前事務(wù)可以讀到其他事務(wù)的未提交的數(shù)據(jù)。如果讀到了臟數(shù)據(jù),即一個(gè)事務(wù)可以讀到另外一個(gè)事務(wù)中未提交的數(shù)據(jù),顯然違反了事務(wù)的隔離性。

臟讀的條件:需要事務(wù)的隔離級別為讀未提交。

示例:

不可重復(fù)讀

不可重復(fù)讀:指在在一個(gè)事務(wù)內(nèi)多次讀取同一個(gè)數(shù)據(jù)集合,在這個(gè)事務(wù)還沒有結(jié)束時(shí),另外一個(gè)事務(wù)也訪問了同一個(gè)數(shù)據(jù)集合,并且做了一些DML操作。因此,在第一個(gè)事務(wù)的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改,第一個(gè)事務(wù)兩次讀取到的數(shù)據(jù)可能是不一樣的(具體看隔離級別)。這種稱為不可重復(fù)讀。

示例:

丟失更新

丟失更新:指一個(gè)事務(wù)的更新操作被另外一個(gè)事務(wù)的更新操作所覆蓋,從而導(dǎo)致數(shù)據(jù)的不一致。

丟失更新的實(shí)例:

解決辦法:對用戶讀取的記錄加上一個(gè)排他鎖,這樣子其他事務(wù)就必須等待前一個(gè)事務(wù)的完成。從而避免并發(fā)問題。

解決辦法的示例:

阻塞

阻塞:事務(wù)因?yàn)榈却渌聞?wù)釋放鎖而等待

超時(shí):等待其他事務(wù)釋放鎖,超過超時(shí)時(shí)間,就認(rèn)為是超時(shí)。

innodb_lock_wait_timeout:用來控制超時(shí)時(shí)間,默認(rèn)是50秒。可以在MYSQL運(yùn)行時(shí)進(jìn)行設(shè)置。

innodb_rollback_on_timeout:用來設(shè)定是否在等待超時(shí)時(shí)對進(jìn)行中的事務(wù)進(jìn)行回滾操作。默認(rèn)是OFF,不回滾。不可以在MySQL啟動時(shí)進(jìn)行修改。用戶在超時(shí)的情況下,必須判斷是是否需要commit或者rollback,之后再進(jìn)行下一步的操作。

死鎖

概念:死鎖是指兩個(gè)或者兩個(gè)以上的事務(wù),因爭奪資源而造成的一種互相等待的現(xiàn)象。若無外力作用,所有事務(wù)都將無法推進(jìn)下去。

解決數(shù)據(jù)庫死鎖最簡單的方法:設(shè)置超時(shí)時(shí)間。即當(dāng)兩個(gè)事務(wù)互相等待時(shí),當(dāng)一個(gè)等待時(shí)間超過設(shè)置的閾值時(shí),其中一個(gè)事務(wù)進(jìn)行回滾,另外一個(gè)等待的事務(wù)就能繼續(xù)執(zhí)行。

超時(shí)機(jī)制雖然簡單,但是其使用FIFO的方式來選擇超時(shí)回滾的事務(wù),假如第一個(gè)超時(shí)的事務(wù) 更新了很多行,遠(yuǎn)比第二個(gè)事務(wù)多,因此占用了更多的undo log,這時(shí)FIFO的方式,就顯得不適用了,因?yàn)榈谝粋€(gè)事務(wù)回滾時(shí)間明顯比第二個(gè)事務(wù)回滾時(shí)間長很多。

等待圖

因?yàn)镕IFO處理死鎖可能不適用,所以數(shù)據(jù)庫普遍采用了wait-for graph(等待圖)的方式來進(jìn)行死鎖檢測。和超時(shí)機(jī)制比較,這是一種更為主動的死鎖檢測方式,InnoDB也采用了這種方式。

等待圖要求數(shù)據(jù)庫保存以下兩種信息:

(1)鎖的信息鏈表(見圖6-5)

(2)事務(wù)等待鏈表(見圖6-5)

通過上述鏈表可以構(gòu)造出一張圖,而在這個(gè)圖中存在回路,則代表存在死鎖。在等待圖中,事務(wù)為圖中的節(jié)點(diǎn)。在圖中,事務(wù)T1指向事務(wù)T2邊的定義為:

(1)事務(wù)T1等待事務(wù)T2所占用的資源

(2)事務(wù)之間在等待相同的資源,而事務(wù)T1在事務(wù)T2之后

發(fā)現(xiàn)死鎖后,InnoDB會馬上回滾一個(gè)事務(wù)。

鎖升級

概念:將當(dāng)前鎖的粒度降低,比如說把行鎖升級為表鎖,那樣子會導(dǎo)致并發(fā)性能降低。

InnoDB不是根據(jù)每個(gè)記錄來產(chǎn)生行鎖的,而是根據(jù)每個(gè)事務(wù)訪問的每個(gè)頁對鎖進(jìn)行管理的,采用的是位圖的方式,因此不管一個(gè)事務(wù)鎖住頁中一條還是多條記錄,都是用一個(gè)鎖,其開銷通常是一致的。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的mysql lock_MySQL-锁总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 美女隐私免费网站 | 中文在线视频观看 | 曰韩精品| 中文字幕福利 | 久久久无码18禁高潮喷水 | 翔田千里一区二区三区av | 日韩欧美国产一区二区在线观看 | 动漫av一区| 亚洲一区二区三区无码久久 | 天天做天天摸天天爽天天爱 | 97黄色网 | 色老头一区二区 | 91视频最新入口 | 久久久欧洲 | 国产极品网站 | 成人无高清96免费 | 天天操夜夜欢 | 三级免费网站 | 国产福利网站 | 91蝌蚪视频在线观看 | 日本熟女一区二区 | 精品视频在线观看一区二区 | 在线观看免费av网站 | 色爽av| 欧美性啪啪 | 午夜中文字幕 | 精品久久在线观看 | 涩涩97| 亚洲av无码一区东京热久久 | 欧美黑人多人双交 | 婷婷视频一区 | 日韩av黄色片 | a免费在线观看 | 色网网站| 免费a大片 | 欧美乱大交xxxxx潮喷l头像 | 黑帮大佬和我的三百六十五天 | 黄色大视频 | 欧美操大逼| 精品少妇久久 | 国产蜜臀av一区二区 | 69式视频| 波多野结衣黄色 | 亚洲美女综合 | 无码人妻黑人中文字幕 | 国产精品123 | 看全色黄大色黄大片女一次牛 | 午夜av大片 | 黄色片网站在线免费观看 | 手机在线视频一区 | 亚洲黄色片在线观看 | 被室友玩屁股(h)男男 | www.在线观看av | 又黄又爽视频在线观看 | julia一区二区三区中文字幕 | 国产成人黄色av | 狠狠干网| 无码av免费精品一区二区三区 | 久久成人18免费观看 | 国产免费91视频 | 怡红院成人影院 | 免费视频网站在线观看入口 | 日本黄色高清视频 | 91在线影院| 国产伦精品一区二区三区精品 | 99久久精品国产一区二区三区 | 美女脱了内裤喂我喝尿视频 | 国产精品--色哟哟 | 久久精品人人做人人爽 | 一区二区三区免费观看 | 被黑人猛躁10次高潮视频 | 欧洲女女同videos | 国产成人综合亚洲 | 男人操女人免费网站 | 自拍偷拍激情视频 | 懂色av蜜臀av粉嫩av分 | 岛国精品 | 成人一区二区三区视频 | 国产免费aa| 黄色网一级片 | 92国产精品 | 国产一级一级国产 | 日韩亚洲欧美在线观看 | 成人免费一区二区三区 | 欧美一区二区三区四区在线 | 蜜桃视频在线播放 | www.伊人网 | 色噜 | 久久牛牛 | 国产叼嘿视频在线观看 | 久久久久久久久久久电影 | 添女人荫蒂视频 | 黄色网一级片 | 夜夜操夜夜操 | 在线观看成人一区 | 日韩在线观看免费全 | 福利社午夜影院 | 欧美 日韩 人妻 高清 中文 | 久久av高潮av无码av喷吹 |