最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解MYSQL的多版本并發(fā)控制MVCC(Multi-Version Concurrency Control)

 更新時(shí)間:2023年10月10日 11:33:24   作者:寅恪光潛  
MVCC是一種用于數(shù)據(jù)庫(kù)管理系統(tǒng)的并發(fā)控制技術(shù),允許多個(gè)事務(wù)同時(shí)訪問(wèn)數(shù)據(jù)庫(kù),而不會(huì)導(dǎo)致讀寫(xiě)沖突,本文就詳細(xì)的介紹了MVCC的具體用法,具有一定的參考價(jià)值,感興趣的可以了解一下

1、概述

MVCC是一種用于數(shù)據(jù)庫(kù)管理系統(tǒng)的并發(fā)控制技術(shù),允許多個(gè)事務(wù)同時(shí)訪問(wèn)數(shù)據(jù)庫(kù),而不會(huì)導(dǎo)致讀寫(xiě)沖突。也就是說(shuō)在讀寫(xiě)的時(shí)候,線程不用去爭(zhēng)搶讀寫(xiě)鎖。因?yàn)榧渔i的過(guò)程比較耗性能。
當(dāng)然很多時(shí)候還是必須的,不能避免,比如說(shuō),去ATM機(jī)取錢(qián)的時(shí)候,同時(shí)又在手機(jī)APP上進(jìn)行提現(xiàn),這種操作就需要加鎖,不能讓其同時(shí)提現(xiàn),一次只能一個(gè)操作,而且只有在ATM取錢(qián)這個(gè)事務(wù)被提交之后才能做其他操作。

處理并發(fā)的場(chǎng)景無(wú)外乎三種:

  • 讀、讀:這個(gè)不需要做控制,因?yàn)閿?shù)據(jù)沒(méi)有變化
  • 讀、寫(xiě):存在線程安全問(wèn)題,可能出現(xiàn)臟讀、幻讀,不可重復(fù)讀
  • 寫(xiě)、寫(xiě):存在線程安全問(wèn)題,可能出現(xiàn)更新丟失的情況

這里介紹的MVCC是在存儲(chǔ)引擎為InnoDB實(shí)現(xiàn)的,目的也是為了提高數(shù)據(jù)庫(kù)的并發(fā)性能,不使用加鎖的方式去處理讀、寫(xiě)并發(fā)。

2、MVCC特點(diǎn)

這里的讀操作,有兩種方式:
快照讀:SELECT語(yǔ)句,在讀寫(xiě)的時(shí)候不用加鎖,所以效率很高,但也存在讀取的時(shí)候有更新操作,可能會(huì)讀到歷史數(shù)據(jù)。

當(dāng)前讀:讀取的是最新數(shù)據(jù),是一種悲觀鎖的操作。它會(huì)對(duì)當(dāng)前讀取的數(shù)據(jù)進(jìn)行加鎖,避免其他事物對(duì)其進(jìn)行寫(xiě)操作。主要包括以下幾種操作:

  • select lock in share mode(共享鎖)
  • select for update(排他鎖)
  • update(排他鎖)
  • insert(排他鎖)
  • delete(排他鎖)

3、準(zhǔn)備數(shù)據(jù)

在介紹之前,沒(méi)有安裝MYSQL的,可以先進(jìn)行安裝,下載地址:https://dev.mysql.com/downloads/
安裝好了之后,我們就新建庫(kù)與表,插入一些數(shù)據(jù)來(lái)做個(gè)測(cè)試

CREATE DATABASE mydb;
USE mydb;
CREATE TABLE `tb1` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
INSERT INTO tb1(name) VALUES ('XIAO1'),('XIAO2'),('XIAO3');
CREATE TABLE `tb2` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam;
INSERT INTO tb2(name) VALUES ('LAO1'),('LAO2'),('LAO3');

這里我特地創(chuàng)建了兩張表,分別是表tb1對(duì)應(yīng)的是InnoDB引擎,表tb2對(duì)應(yīng)的是myisam引擎,創(chuàng)建之后,也可以看到兩者的數(shù)據(jù)格式也是不一樣的,我們先查詢(xún)下,新建的數(shù)據(jù)庫(kù)mydb以及保存的數(shù)據(jù)在什么地方:

mysql> show variables like '%datadir%';
+---------------+---------------------------------------------+
| Variable_name | Value                                       |
+---------------+---------------------------------------------+
| datadir       | C:\ProgramData\MySQL\MySQL Server 8.0\Data\ |
+---------------+---------------------------------------------+
1 row in set, 1 warning (0.00 sec)

然后可以看到,InnoDB引擎對(duì)應(yīng)的是:tb1.ibd myisam對(duì)應(yīng)的是:tb2.MYD(數(shù)據(jù))、tb2.MYI(索引)、tb2_402.sdi(表結(jié)構(gòu))[這個(gè)在以前的版本沒(méi)有出現(xiàn)]
MySQL5.5之后都是默認(rèn)為InnoDB引擎

4、MVCC原理

MYSQL存儲(chǔ)的數(shù)據(jù)中,除了我們顯式定義的字段,還隱含著兩個(gè)字段。
trx_id:事務(wù)id,每進(jìn)行一次事務(wù)操作,就會(huì)自增1。
roll_pointer:回滾指針,用于找到上一個(gè)版本的數(shù)據(jù),結(jié)合undolog進(jìn)行回滾。

我們用SELECT讀數(shù)據(jù)時(shí),這一時(shí)刻的數(shù)據(jù)會(huì)有很多個(gè)版本【比如上圖四個(gè)版本】,但我們并不知道讀取哪個(gè)版本,依賴(lài)ReadView來(lái)對(duì)我們進(jìn)行版本的選擇,通過(guò)ReadView我們就能夠知道讀取哪個(gè)版本。我們來(lái)看下這個(gè)ReadView的定義:

class ReadView {
/* ... */
private:
trx_id_t m_low_limit_id; /* 大于等于這個(gè) ID 的事務(wù)均不可見(jiàn) */
trx_id_t m_up_limit_id; /* 小于這個(gè) ID 的事務(wù)均可見(jiàn) */
trx_id_t m_creator_trx_id; /* 創(chuàng)建該 Read View 的事務(wù)ID */
trx_id_t m_low_limit_no; /* 事務(wù) Number, 小于該 Number 的 Undo Logs 均可以被 Purge */
ids_t m_ids; /* 創(chuàng)建 Read View 時(shí)的活躍事務(wù)列表 */
m_closed; /* 標(biāo)記 Read View 是否 close */
}

字段的解釋?zhuān)?/p>

  • m_low_limit_id:目前出現(xiàn)的最大事務(wù)ID+1(下一個(gè)將被分配的事務(wù)ID)。大于等于這個(gè)ID的數(shù)據(jù)版本均不可見(jiàn),也就訪問(wèn)不到。
  • m_up_limit_id:活躍事務(wù)列表m_ids中最小的事務(wù)ID,如果為空,則m_up_limit_id為m_low_limit_id。小于這個(gè)ID的數(shù)據(jù)版本均可見(jiàn)。
  • m_ids:ReadView創(chuàng)建時(shí)其他未提交的活躍事務(wù)ID列表。創(chuàng)建ReadView時(shí),將當(dāng)前未提交事務(wù)ID記錄下來(lái),后續(xù)即使它們修改了記錄行的值,對(duì)于當(dāng)前事務(wù)也是不可見(jiàn)的。m_ids 不包括當(dāng)前事務(wù)自己和已提交的事務(wù)(正在內(nèi)存中)
  • m_creator_trx_id:創(chuàng)建該ReadView的事務(wù)ID

5、實(shí)踐操作

開(kāi)四個(gè)終端,新建三個(gè)事務(wù),兩個(gè)寫(xiě)操作,一個(gè)讀操作,還有一個(gè)就是單純的查詢(xún)。大家可以根據(jù)不同的進(jìn)入時(shí)間來(lái)了解這個(gè)過(guò)程,會(huì)產(chǎn)生未提交和已提交事務(wù)狀態(tài),對(duì)應(yīng)的查詢(xún)信息都是不一樣的,具體代碼分別如下:

BEGIN;
UPDATE tb1 SET  name='XXX' WHERE id=1;
UPDATE tb1 SET  name='YYY' WHERE id=1;
COMMIT;
BEGIN;
UPDATE tb1 SET  name='ZZZ' WHERE id=1;
UPDATE tb1 SET  name='QQQ' WHERE id=1;
DELETE FROM tb1 WHERE id=5;
COMMIT;
BEGIN;
SELECT * FROM tb1 WHERE id=1;
COMMIT;
SELECT * FROM tb1;

6、小結(jié)

對(duì)于這種讀寫(xiě)并發(fā),以及對(duì)性能的要求,大家需要看實(shí)際業(yè)務(wù)情況來(lái)做決定,其中這里主要是介紹InnoDB引擎,這個(gè)要高效很多,在以前的舊版本可能大家使用MyISAM這個(gè)更多,因?yàn)樾阅芎芎?,不過(guò)不支持事務(wù)操作,所以很多場(chǎng)景也就不適應(yīng),MYSQL5.5版本之后就是默認(rèn)InnoDB引擎了。
最后大家也可以嘗試在表tb2中去嘗試下,看下是什么結(jié)果,因?yàn)檫@張表使用的是MyISAM引擎,就起不到作用了。
另外需要注意的是,事務(wù)的提交是默認(rèn)自動(dòng)的,有些時(shí)候需要關(guān)閉,將默認(rèn)的1修改為0:

SET AUTOCOMMIT=0;
SELECT @@AUTOCOMMIT;

比如說(shuō)對(duì)于臟讀的情況,我們需要當(dāng)前讀,也就是需要排它鎖:

SET AUTOCOMMIT=0;
BEIGIN;
DELETE FROM tb1 WHERE id=2;

這種情況如果我們的事務(wù)在這個(gè)時(shí)候進(jìn)去,對(duì)這個(gè)id=2進(jìn)行讀寫(xiě)操作,就會(huì)出現(xiàn)臟讀的情況,這個(gè)時(shí)候就需要使用SELECT FOR UPDATE,等待事務(wù)處理完畢之后再做相應(yīng)的操作。

對(duì)于臟讀這種情況,很常見(jiàn),比如說(shuō)事務(wù)在做刪除操作,這個(gè)時(shí)候記錄已被刪除但是還沒(méi)有提交事務(wù),如果進(jìn)行查詢(xún)操作就會(huì)出現(xiàn)臟讀,如下:

SET AUTOCOMMIT=0;
BEGIN;
SELECT * FROM tb1 WHERE id=2 FOR UPDATE;
UPDATE tb1 SET  name='QQQ' WHERE id=1;
COMMIT;

到此這篇關(guān)于一文詳解MYSQL的多版本并發(fā)控制MVCC(Multi-Version Concurrency Control)的文章就介紹到這了,更多相關(guān)MYSQL多版本并發(fā)控制MVCC內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL對(duì)字符串使用STR_TO_DATE()函數(shù)詳解

    MySQL對(duì)字符串使用STR_TO_DATE()函數(shù)詳解

    文章介紹了MySQL中的STR_TO_DATE()函數(shù),用于將字符串轉(zhuǎn)換為日期時(shí)間類(lèi)型,轉(zhuǎn)換時(shí)需要注意字符串格式、日期有效性等問(wèn)題
    2025-03-03
  • mysql中insert與select的嵌套使用方法

    mysql中insert與select的嵌套使用方法

    這篇文章主要介紹了mysql中insert與select的嵌套使用方法,代碼功能非常實(shí)用,需要的朋友可以參考下
    2014-07-07
  • java連接mysql數(shù)據(jù)庫(kù)useSSL問(wèn)題及解決

    java連接mysql數(shù)據(jù)庫(kù)useSSL問(wèn)題及解決

    文章總結(jié):通過(guò)分析錯(cuò)誤日志和配置文件,發(fā)現(xiàn)問(wèn)題由SSL相關(guān)配置引起,MySQL和proxysql的SSL配置不同導(dǎo)致連接失敗,最終通過(guò)修改JDBC?URL添加useSSL=false參數(shù),解決了連接問(wèn)題,建議使用高版本JDBC驅(qū)動(dòng),并明確配置useSSL
    2025-11-11
  • Linux下安裝與使用MySQL詳細(xì)介紹

    Linux下安裝與使用MySQL詳細(xì)介紹

    以下是對(duì)在Linux下安裝與使用MySQL進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • MySQL高級(jí)查詢(xún)之與Group By集合使用介紹

    MySQL高級(jí)查詢(xún)之與Group By集合使用介紹

    在MySQL中,你可以獲取表達(dá)式組合的連接值。你可以使用DISTINCT刪去重復(fù)值。假若你希望多結(jié)果值進(jìn)行排序,則應(yīng)該使用 ORDER BY子句
    2013-08-08
  • 使用navicat 8實(shí)現(xiàn)創(chuàng)建數(shù)據(jù)庫(kù)和導(dǎo)入數(shù)據(jù) 管理用戶(hù)與權(quán)限[圖文方法]

    使用navicat 8實(shí)現(xiàn)創(chuàng)建數(shù)據(jù)庫(kù)和導(dǎo)入數(shù)據(jù) 管理用戶(hù)與權(quán)限[圖文方法]

    使用navicat8實(shí)現(xiàn)創(chuàng)建數(shù)據(jù)庫(kù)和導(dǎo)入數(shù)據(jù)的方法,需要的朋友可以參考下。
    2011-04-04
  • 最新評(píng)論

    抚宁县| 淮安市| 汉川市| 星座| 永修县| 沅江市| 清苑县| 藁城市| 密云县| 交口县| 栾城县| 堆龙德庆县| 调兵山市| 民和| 瑞安市| 铁力市| 察哈| 新宁县| 宁城县| 峨眉山市| 沈丘县| 东乡县| 高密市| 新竹县| 宜兰市| 高州市| 阜平县| 云安县| 玛沁县| 温州市| 南部县| 通许县| 玛多县| 闵行区| 炉霍县| 济源市| 新化县| 崇文区| 仪陇县| 大余县| 湘西|