日韩欧美国产精品免费一二-日韩欧美国产精品亚洲二区-日韩欧美国产精品专区-日韩欧美国产另-日韩欧美国产免费看-日韩欧美国产免费看清风阁

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

打臉實(shí)錄:MySQL插入是并發(fā)還是串行?

admin
2024年7月26日 17:8 本文熱度 1482

最近筆者和同事?tīng)?zhēng)辯起來(lái),MySQL插入是并發(fā)還是串行,我記得明明是串行插入,同事非要和我杠,說(shuō)MySQL可以并發(fā)插入。


我要親自試驗(yàn)一下,打他的臉!


MySQL實(shí)驗(yàn)版本:8.0。


一、定義表結(jié)構(gòu)


首先定義 用戶信息表userInfo,其中id為自增,name具有唯一索引。


CREATE TABLE `userInfo` (  `id` int NOT NULL AUTO_INCREMENT,  `name` varchar(50) NOT NULL,  `password` varchar(50) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `name` (`name`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4

二、驗(yàn)證流程


默認(rèn)情況下,在命令行中 MySQL會(huì)自動(dòng)提交,每個(gè)SQL執(zhí)行會(huì)非常快,無(wú)法驗(yàn)證同時(shí)執(zhí)行的兩個(gè)事務(wù)之間是否存在阻塞情況,所以需要顯示開(kāi)啟事務(wù)和提交事務(wù)。


1.驗(yàn)證


首先,我們開(kāi)啟兩個(gè)事務(wù)。在事務(wù)1中,首先插入一條記錄,暫時(shí)不提交。然后,在事務(wù)2中開(kāi)啟一個(gè)新的事務(wù),并插入一條自增記錄。


如果MySQL的innodb插入是串行的,那么此時(shí)事務(wù)2的插入記錄將會(huì)被阻塞。如果沒(méi)有被阻塞,那就說(shuō)明MySQL的innodb插入是并發(fā)執(zhí)行的。



2.實(shí)驗(yàn)驗(yàn)證


事務(wù)2 的執(zhí)行記錄:



如上圖所示,在事務(wù)1還未提交,事務(wù)2在事務(wù)1的間隙中插入一條記錄,插入操作立即成功,并且事務(wù)2的自增主鍵ID為2。這說(shuō)明在MySQL中,當(dāng)一個(gè)事務(wù)正在插入記錄時(shí),并不會(huì)阻塞其他事務(wù)的插入。


在MySQL中,多個(gè)事務(wù)之間的插入操作是并發(fā)進(jìn)行的,而不是串行進(jìn)行的。


我感覺(jué)自己的臉熱熱的,小丑竟是我自己,趕緊給同事認(rèn)了錯(cuò)……


我的認(rèn)知一直是錯(cuò)誤的。


但是在底層存儲(chǔ)層面,MySQL會(huì)對(duì)數(shù)據(jù)頁(yè)加鎖。如果兩條記錄在同一個(gè)數(shù)據(jù)頁(yè),實(shí)際寫(xiě)入是串行的,但是事務(wù)層面是并發(fā)的。


想象一下,庫(kù)存扣減和新增庫(kù)存流水在同一個(gè)事務(wù)中,如果新增庫(kù)存流水是串行的,那將極大的降低庫(kù)存事務(wù)的并發(fā)度啊。


本以為驗(yàn)證結(jié)束,打卡下班,結(jié)果發(fā)現(xiàn) MySQL插入似乎存在幻讀問(wèn)題!


從下圖中可以觀察到,事務(wù)1在插入時(shí)似乎確實(shí)出現(xiàn)了幻讀問(wèn)題!


事務(wù) 1 的執(zhí)行記錄顯示,事務(wù)1先于事務(wù)2開(kāi)啟,但是事務(wù)1期間可以查詢到事務(wù)2提交的記錄。這說(shuō)明有幻讀問(wèn)題!



三、為什么出現(xiàn)幻讀?


所謂幻讀,是指在一個(gè)事務(wù)讀取記錄時(shí),另一個(gè)事務(wù)在此時(shí)插入或刪除了一條記錄,導(dǎo)致第一個(gè)事務(wù)再次讀取時(shí)發(fā)現(xiàn)記錄的數(shù)量發(fā)生了變化。


要想理解出現(xiàn)幻讀的原因,需要先了解MySQL是如何解決幻讀問(wèn)題的。


為了解決幻讀問(wèn)題,MySQL采用了間隙鎖和多版本并發(fā)控制(MVCC)的方法。間隙鎖會(huì)鎖定一段記錄的范圍,其他事務(wù)無(wú)法對(duì)這些記錄進(jìn)行更新或刪除操作。這樣,當(dāng)當(dāng)前事務(wù)再次進(jìn)行查詢時(shí),就不會(huì)出現(xiàn)記錄數(shù)量的新增或減少的情況了。


1.MySQL 插入時(shí)加了什么鎖?


MySQL 插入時(shí)存在幻讀問(wèn)題,說(shuō)明MySQL 并沒(méi)有加間隙鎖,主要考慮也是為了提高插入時(shí)并發(fā)度,如果添加間隙鎖,勢(shì)必導(dǎo)致插入并發(fā)度降低!MySQL 在插入之前會(huì)申請(qǐng) 插入意向鎖,而記錄本身不沖突(無(wú)唯一鍵沖突)插入意向鎖就不會(huì)沖突。


MySQL 文檔中記錄了 插入意向鎖


插入意向鎖(insert intention lock)是一種由插入操作在插入行之前設(shè)置的鎖定類(lèi)型。這種鎖定方式表示插入的意圖,使得在相同索引間隙上進(jìn)行插入的多個(gè)事務(wù)在插入位置不沖突的情況下不需要互相等待。假設(shè)索引記錄中存在值為4和7的記錄。分別嘗試插入值為5和6的兩個(gè)不同事務(wù),在獲得插入行的排他鎖之前,它們會(huì)先使用插入意向鎖鎖定位于4和7之間的間隙,并且由于插入行不沖突,它們不會(huì)互相阻塞。


2.插入場(chǎng)景 MVCC 不生效?


除更新場(chǎng)景外,查詢場(chǎng)景也有幻讀的困惱。如果第一次查詢時(shí)只有3條記錄,再次查詢則變?yōu)?條,實(shí)在過(guò)于奇幻。


如果給普通的查詢語(yǔ)句添加間隙鎖,勢(shì)必極大的降低MySQL 的并發(fā)度,如果不能使用間隙鎖,還有哪些辦法解決幻讀呢?


MySQL 通過(guò)引入MVCC解決查詢場(chǎng)景的幻讀問(wèn)題。MVCC是多版本并發(fā)控制(Multiversion Concurrency Control)的縮寫(xiě),在MVCC中,每個(gè)事務(wù)可以看到數(shù)據(jù)庫(kù)的一個(gè)穩(wěn)定的快照,而不會(huì)被其他并發(fā)事務(wù)的修改所干擾。當(dāng)一個(gè)事務(wù)修改數(shù)據(jù)庫(kù)時(shí),它會(huì)創(chuàng)建一個(gè)新的數(shù)據(jù)版本,而不是直接在原始數(shù)據(jù)上進(jìn)行修改。而其他事務(wù)仍然可以讀取原始數(shù)據(jù)的舊版本或者已經(jīng)提交的新版本,這樣就避免了讀取到未提交的數(shù)據(jù)或者被其他事務(wù)的寫(xiě)操作所阻塞。


MVCC的實(shí)現(xiàn)通常涉及對(duì)每個(gè)數(shù)據(jù)行或數(shù)據(jù)塊分配一個(gè)唯一的標(biāo)識(shí)符,稱為"事務(wù)ID"。每個(gè)事務(wù)也有自己的唯一ID。當(dāng)一個(gè)事務(wù)讀取數(shù)據(jù)時(shí),系統(tǒng)會(huì)檢查該數(shù)據(jù)的事務(wù)ID與事務(wù)的ID是否兼容,以確定是否允許讀取。如果事務(wù)的ID大于數(shù)據(jù)的事務(wù)ID,那么說(shuō)明數(shù)據(jù)是過(guò)期的,事務(wù)將無(wú)法讀取。這種機(jī)制保證了事務(wù)在讀取數(shù)據(jù)時(shí)的隔離性和一致性。


3.轉(zhuǎn)機(jī)出現(xiàn)了


當(dāng)我在苦苦思考,為什么MVCC 沒(méi)有生效時(shí),我隨手重新測(cè)試發(fā)現(xiàn),如果在 insert 語(yǔ)句之前,使用 select 查詢一下,就不會(huì)出現(xiàn)幻讀問(wèn)題。


操作順序如下:



我在事務(wù)1,開(kāi)啟事務(wù)以后,新增了 select 語(yǔ)句查詢,而后第六步,就不會(huì)再有幻讀問(wèn)題……


這實(shí)在太奇幻了,一波三折……


由此可見(jiàn) MySQL 插入并沒(méi)有幻讀問(wèn)題,只是我的打開(kāi)方式不對(duì)。我應(yīng)該先 select一下 ……,終究還是我錯(cuò)了,但是我想問(wèn)為什么?我為什么錯(cuò)了?


4.ReadView 是關(guān)鍵!


除MVCC 外,MySQL InnoDB 引擎設(shè)計(jì)了 ReadView(可讀視圖) 的概念。


ReadView 判斷記錄的可見(jiàn)性,ReadView 實(shí)際上是當(dāng)前系統(tǒng)中所有活躍事務(wù)的列表,主要包含以下組成部分:


  • m_ids:在生成 ReadView 時(shí)當(dāng)前系統(tǒng)中活躍的事務(wù) ID 列表;

  • min_trx_id:在生成 ReadView 時(shí)當(dāng)前系統(tǒng)中活躍的事務(wù)中最小的事務(wù) ID,也就是 m_ids 中的最小值;

  • max_trx_id:在生成 ReadView 時(shí)系統(tǒng)中應(yīng)該分配給下一個(gè)事務(wù)的 ID 值;

  • creator_trx_id:生成 ReadView 的事務(wù)對(duì)應(yīng)的事務(wù) ID,也就是當(dāng)前事務(wù) ID。


有了這個(gè) ReadView 之后,在訪問(wèn)某條記錄時(shí),只需要按照下邊的步驟判斷該記錄的某個(gè)版本是否可見(jiàn):


1)如果被訪問(wèn)版本的 trx_id 屬性值與 ReadView 中的 creator_trx_id 值相同,意味著當(dāng)前事務(wù)在訪問(wèn)它自己修改過(guò)的記錄,所以該版本記錄可以被當(dāng)前事務(wù)訪問(wèn)。


2)如果被訪問(wèn)版本的 trx_id 屬性值小于 ReadView 中的 min_trx_id 值,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成 ReadView 前已經(jīng)提交,所以該版本記錄可以被當(dāng)前事務(wù)訪問(wèn)。


3)如果被訪問(wèn)版本的 trx_id 屬性值大于或等于 ReadView 中的 max_trx_id 值,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成 ReadView 后才開(kāi)啟,所以該版本記錄不可以被當(dāng)前事務(wù)訪問(wèn)。


4)如果被訪問(wèn)版本的 trx_id 屬性值在 ReadView 的 min_trx_id 和 max_trx_id 之間,那就需要判斷一下 trx_id 屬性值是不是在 m_ids 列表中,如果在,說(shuō)明創(chuàng)建 ReadView 時(shí)生成該版本的事務(wù)還是活躍的,該版本不可以被訪問(wèn);如果不在,說(shuō)明創(chuàng)建 ReadView 時(shí)生成該版本的事務(wù)已經(jīng)被提交,該版本記錄可以被訪問(wèn)。如果某個(gè)版本的記錄對(duì)當(dāng)前事務(wù)不可見(jiàn)的話,那就順著版本鏈找到下一個(gè)版本的數(shù)據(jù),繼續(xù)按照上邊的步驟判斷可見(jiàn)性,依此類(lèi)推,直到版本鏈中的最后一個(gè)版本。如果最后一個(gè)版本也不可見(jiàn)的話,那么就意味著該條記錄對(duì)該事務(wù)完全不可見(jiàn),查詢結(jié)果就不包含該記錄。


總結(jié)一下就是:如果當(dāng)前事務(wù)id的生成時(shí)間發(fā)生在 記錄的更新之后,那么當(dāng)前事務(wù)就可以看見(jiàn)這個(gè)記錄,否則看不見(jiàn)!避免幻讀問(wèn)題。


那 ReadView 又是何時(shí)生成的呢?


在 Read committed RC 隔離級(jí)別下,每個(gè)事務(wù)執(zhí)行第一個(gè) SELECT 語(yǔ)句時(shí),會(huì)將當(dāng)前系統(tǒng)中的所有的活躍事務(wù)拷貝到一個(gè)列表生成 ReadView,后續(xù)所有的 SELECT 都是復(fù)用這個(gè) ReadView。


REPEATABLE READ RR 隔離級(jí)別下,只有第一次 SELECT 才會(huì)生成 ReadView,后續(xù) SELECT 都會(huì)復(fù)用這個(gè) ReadView,也就不存在新提交事務(wù)對(duì)這個(gè) ReadView 的影響了。


所以 當(dāng)我在 事務(wù) 1 新增select語(yǔ)句,會(huì)生成一個(gè)ReadView,這個(gè)ReadView 生成時(shí)間要早于 事務(wù)2的時(shí)間,所以事務(wù)1 的后續(xù)所有查詢都不會(huì)看到事務(wù)2的記錄,從而避免幻讀問(wèn)題發(fā)生。


總結(jié)


  • MySQL innodb 插入記錄是并發(fā)的。

  • MySQL innodb 插入記錄不存在幻讀問(wèn)題,MySQL 通過(guò) mvcc+ ReadView解決幻讀問(wèn)題。


作者丨五陽(yáng)神功
來(lái)源丨稀土掘金:juejin.cn/post/7297608058476249124


該文章在 2024/7/26 17:08:15 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 日本一区二区三区视频 | 日本中文字幕乱码免费 | 好吊视频一区二区三区 | 国产私拍福利精 | 成人精品一区二区三四 | 最近中文字幕mv | 欧美在线观看一区 | 国产国产人免费人成免费视频 | 日本三级免费网站 | 999在线观看国产 | 91短视频污下载 | 后进极品翘臀在线播放 | 欧美日韩一区免费观看 | 91精品啪在线观看国产老人令品 | 自偷自拍| www.色色资源站 | 小蜜被两老头 | 欧美日韩亚洲国产精品自拍 | 欧美不卡一卡二 | 日韩一级一欧美一级国产 | 中日韩va无 | 日韩成人精品无v国产 | 最新亚洲人 | 中文字幕一精品亚洲无线一区 | 日本中文字幕一区二区有码 | 桃花视频免 | 98视频在线 | 国产精品一区福利在线观看 | 最快无弹窗小说阅读网 | 福利国产视频一区二区 | 欧美一卡二三 | 亚洲国产一区二区在线免费 | 91香蕉国产亚洲一二三区 | 国语对白精品一区二区在线观看 | 亚洲一级二级三级四级 | 亚洲国产美国国产综合一区 | 亚洲丝袜在线观看 | 亚洲国产精品自在现线让你爽 | 国产国产人成免费视频77777 | 国产精品福利在线观看免费 | 亚洲日韩高清在线亚洲专区 |