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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

window.open 实现session隔离_InnoDB存储引擎MVCC实现原理

發(fā)布時(shí)間:2024/9/19 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 window.open 实现session隔离_InnoDB存储引擎MVCC实现原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)單背景介紹

MySQL

MySQL是現(xiàn)在最流行的關(guān)系型數(shù)據(jù)庫(kù)(RDB)的選擇, 創(chuàng)建一個(gè)應(yīng)用時(shí),無(wú)論是用戶(hù)數(shù)據(jù)還是訂單數(shù)據(jù),使用關(guān)系型數(shù)據(jù)庫(kù)存儲(chǔ)是最可靠穩(wěn)定的選擇,借助RDB提供的可靠性、事務(wù)等功能,為應(yīng)用提供完善的支持。MySQL是開(kāi)源軟件,可以免費(fèi)使用,MySQL在發(fā)展多年后越來(lái)越成熟,成為大部分公司的數(shù)據(jù)庫(kù)首選。MySQL采用插件式的存儲(chǔ)引擎架構(gòu),5.5版本后默認(rèn)使用InnoDB存儲(chǔ)引擎。

MySQL架構(gòu)

MySQL從概念上可以分為四層,頂層是接入層,不同語(yǔ)言的客戶(hù)端通過(guò)mysql的協(xié)議與mysql服務(wù)器進(jìn)行連接通信,接入層進(jìn)行權(quán)限驗(yàn)證、連接池管理、線程管理等。下面是mysql服務(wù)層,包括sql解析器、sql優(yōu)化器、數(shù)據(jù)緩沖、緩存等。再下面是mysql中的存儲(chǔ)引擎層,mysql中存儲(chǔ)引擎是基于表的。最后是系統(tǒng)文件層,保存數(shù)據(jù)、索引、日志等。

MVCC

MVCC是Multi Version Concurrency Control的簡(jiǎn)稱(chēng),代表多版本并發(fā)控制。為什么需要MVCC,還要從數(shù)據(jù)庫(kù)事務(wù)的ACID特性說(shuō)起。

相信很多朋友都了解ACID,它們分別代表了Atomicity(原子性), Consistency(一致性), Isolation(隔離性), Durability(持久性)。

原子性表示一個(gè)事務(wù)的操作結(jié)果要么全部執(zhí)行要么全部不執(zhí)行。

一致性表示事務(wù)總是從一個(gè)一致的狀態(tài)轉(zhuǎn)換到另一個(gè)一致的狀態(tài)。

隔離性表示一個(gè)事務(wù)的修改結(jié)果在什么時(shí)間能夠被其他事務(wù)看到,SQL1992規(guī)范中對(duì)隔離性定義了不同的隔離級(jí)別,

分為讀未提交(READ UNCOMMITED),事務(wù)能夠看到其他事務(wù)沒(méi)有提及的修改,當(dāng)另一個(gè)事務(wù)又回滾了修改后的情況又被稱(chēng)為臟讀dirty read。

讀已提交(READ COMMITTED),事務(wù)能夠看到其他事務(wù)提交后的修改,這時(shí)會(huì)出現(xiàn)一個(gè)事務(wù)內(nèi)兩次讀取數(shù)據(jù)可能因?yàn)槠渌聞?wù)提交的修改導(dǎo)致不一致的情況,稱(chēng)為不可重復(fù)讀。 可重復(fù)讀(REPEATABLE READ),在兩次讀取時(shí)讀取到的數(shù)據(jù)的狀態(tài)是一致的,和序列化(SERIALIZABLE)可重復(fù)讀中可能出現(xiàn)第二次讀讀到第一次沒(méi)有讀到的數(shù)據(jù),也就是被其他事務(wù)插入的數(shù)據(jù),這種情況稱(chēng)為幻讀phantom read, 序列化級(jí)別中不能出現(xiàn)幻讀。

隔離級(jí)別依次增強(qiáng),但是導(dǎo)致的問(wèn)題是并發(fā)能力的減弱。

各種數(shù)據(jù)庫(kù)廠商會(huì)對(duì)各個(gè)隔離級(jí)別進(jìn)行實(shí)現(xiàn)。

和Java中的多線程問(wèn)題相同,數(shù)據(jù)庫(kù)通常使用鎖來(lái)實(shí)現(xiàn)隔離性。

最原生的鎖,鎖住一個(gè)資源后會(huì)禁止其他任何線程訪問(wèn)同一個(gè)資源。但是很多應(yīng)用的一個(gè)特點(diǎn)都是讀多寫(xiě)少的場(chǎng)景,很多數(shù)據(jù)的讀取次數(shù)遠(yuǎn)大于修改的次數(shù),而讀取數(shù)據(jù)間互相排斥顯得不是很必要。所以就使用了一種讀寫(xiě)鎖的方法,讀鎖和讀鎖之間不互斥,而寫(xiě)鎖和寫(xiě)鎖、讀鎖都互斥。這樣就很大提升了系統(tǒng)的并發(fā)能力。之后人們發(fā)現(xiàn)并發(fā)讀還是不夠,又提出了能不能讓讀寫(xiě)之間也不沖突的方法,就是讀取數(shù)據(jù)時(shí)通過(guò)一種類(lèi)似快照的方式將數(shù)據(jù)保存下來(lái),這樣讀鎖就和寫(xiě)鎖不沖突了,不同的事務(wù)session會(huì)看到自己特定版本的數(shù)據(jù)。當(dāng)然快照是一種概念模型,不同的數(shù)據(jù)庫(kù)可能用不同的方式來(lái)實(shí)現(xiàn)這種功能。

之后的討論默認(rèn)均以REPEATABLE READ作為隔離級(jí)別。

InnoDB與MVCC

MySQL中的InnoDB存儲(chǔ)引擎的特性有,默認(rèn)隔離級(jí)別REPEATABLE READ, 行級(jí)鎖,實(shí)現(xiàn)了MVCC, Consistent nonlocking read(默認(rèn)讀不加鎖,一致性非鎖定讀), Insert Buffer, Adaptive Hash Index, DoubleWrite, Cluster Index。

上面列舉了這么多,表示InnoDB有很多特性、很快。

InnoDB中通過(guò)UndoLog實(shí)現(xiàn)了數(shù)據(jù)的多版本,而并發(fā)控制通過(guò)鎖來(lái)實(shí)現(xiàn)。

Undo Log除了實(shí)現(xiàn)MVCC外,還用于事務(wù)的回滾。

Redo log, bin log, Undo log

MySQL Innodb中存在多種日志,除了錯(cuò)誤日志、查詢(xún)?nèi)罩就?#xff0c;還有很多和數(shù)據(jù)持久性、一致性有關(guān)的日志。

binlog,是mysql服務(wù)層產(chǎn)生的日志,常用來(lái)進(jìn)行數(shù)據(jù)恢復(fù)、數(shù)據(jù)庫(kù)復(fù)制,常見(jiàn)的mysql主從架構(gòu),就是采用slave同步master的binlog實(shí)現(xiàn)的, 另外通過(guò)解析binlog能夠?qū)崿F(xiàn)mysql到其他數(shù)據(jù)源(如ElasticSearch)的數(shù)據(jù)復(fù)制。

redo log記錄了數(shù)據(jù)操作在物理層面的修改,mysql中使用了大量緩存,緩存存在于內(nèi)存中,修改操作時(shí)會(huì)直接修改內(nèi)存,而不是立刻修改磁盤(pán),當(dāng)內(nèi)存和磁盤(pán)的數(shù)據(jù)不一致時(shí),稱(chēng)內(nèi)存中的數(shù)據(jù)為臟頁(yè)(dirty page)。為了保證數(shù)據(jù)的安全性,事務(wù)進(jìn)行中時(shí)會(huì)不斷的產(chǎn)生redo log,在事務(wù)提交時(shí)進(jìn)行一次flush操作,保存到磁盤(pán)中, redo log是按照順序?qū)懭氲?#xff0c;磁盤(pán)的順序讀寫(xiě)的速度遠(yuǎn)大于隨機(jī)讀寫(xiě)。當(dāng)數(shù)據(jù)庫(kù)或主機(jī)失效重啟時(shí),會(huì)根據(jù)redo log進(jìn)行數(shù)據(jù)的恢復(fù),如果redo log中有事務(wù)提交,則進(jìn)行事務(wù)提交修改數(shù)據(jù)。這樣實(shí)現(xiàn)了事務(wù)的原子性、一致性和持久性。

Undo Log: 除了記錄redo log外,當(dāng)進(jìn)行數(shù)據(jù)修改時(shí)還會(huì)記錄undo log,undo log用于數(shù)據(jù)的撤回操作,它記錄了修改的反向操作,比如,插入對(duì)應(yīng)刪除,修改對(duì)應(yīng)修改為原來(lái)的數(shù)據(jù),通過(guò)undo log可以實(shí)現(xiàn)事務(wù)回滾,并且可以根據(jù)undo log回溯到某個(gè)特定的版本的數(shù)據(jù),實(shí)現(xiàn)MVCC。

redo log 和binlog的一致性,為了防止寫(xiě)完binlog但是redo log的事務(wù)還沒(méi)提交導(dǎo)致的不一致,innodb 使用了兩階段提交

大致執(zhí)行序列為

InnoDB prepare (持有prepare_commit_mutex);

write/sync Binlog;

InnoDB commit (寫(xiě)入COMMIT標(biāo)記后釋放prepare_commit_mutex)。

MVCC實(shí)現(xiàn)

innodb中通過(guò)B+樹(shù)作為索引的數(shù)據(jù)結(jié)構(gòu),并且主鍵所在的索引為ClusterIndex(聚簇索引), ClusterIndex中的葉子節(jié)點(diǎn)中保存了對(duì)應(yīng)的數(shù)據(jù)內(nèi)容。一個(gè)表只能有一個(gè)主鍵,所以只能有一個(gè)聚簇索引,如果表沒(méi)有定義主鍵,則選擇第一個(gè)非NULL唯一索引作為聚簇索引,如果還沒(méi)有則生成一個(gè)隱藏id列作為聚簇索引。

除了Cluster Index外的索引是Secondary Index(輔助索引)。輔助索引中的葉子節(jié)點(diǎn)保存的是聚簇索引的葉子節(jié)點(diǎn)的值。

InnoDB行記錄中除了剛才提到的rowid外,還有trx_id和db_roll_ptr, trx_id表示最近修改的事務(wù)的id,db_roll_ptr指向undo segment中的undo log。

新增一個(gè)事務(wù)時(shí)事務(wù)id會(huì)增加,trx_id能夠表示事務(wù)開(kāi)始的先后順序。

Undo log分為Insert和Update兩種,delete可以看做是一種特殊的update,即在記錄上修改刪除標(biāo)記。

update undo log記錄了數(shù)據(jù)之前的數(shù)據(jù)信息,通過(guò)這些信息可以還原到之前版本的狀態(tài)。

當(dāng)進(jìn)行插入操作時(shí),生成的Insert undo log在事務(wù)提交后即可刪除,因?yàn)槠渌聞?wù)不需要這個(gè)undo log。

進(jìn)行刪除修改操作時(shí),會(huì)生成對(duì)應(yīng)的undo log,并將當(dāng)前數(shù)據(jù)記錄中的db_roll_ptr指向新的undo log

數(shù)據(jù)可見(jiàn)性判斷

CREATE TABLE `testunique` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,

`uid` int(11) DEFAULT NULL,

`ukey` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `id_uid` (`uid`),

KEY `index_key` (`ukey`)

) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=utf8;

隔離級(jí)別REPEATABLE READ

只有當(dāng)session2 commit之后的查詢(xún)才能查到session1插入的數(shù)據(jù)

事務(wù)可見(jiàn)性的處理過(guò)程:

RR級(jí)別下一個(gè)事務(wù)開(kāi)始后第一個(gè)snapshot read的時(shí)候,會(huì)將當(dāng)期活動(dòng)的事務(wù)id記錄下來(lái),記錄到read view中。RC級(jí)別則是每次snapshot read都會(huì)創(chuàng)建一個(gè)新的read view。

假設(shè)當(dāng)前,read view中最大的事務(wù)id為tmax, 最小為tmin。則判斷一個(gè)數(shù)據(jù)是否可見(jiàn)以及對(duì)應(yīng)的版本的方法為。

如果該行中的trx_id, 賦值給tid, 如果tid和當(dāng)前事務(wù)id相等或小于tmin,說(shuō)明是事務(wù)內(nèi)發(fā)生的或開(kāi)啟前的修改,則直接返回該版本數(shù)據(jù); 如果

trx_id大于tmax, 則查看該版本的db_roll_ptr中的trx_id,賦值給tid并從頭開(kāi)始判斷。如果tid小于tmax并且不在read view中,則返回,否則中回滾段中找出undo log的trx_id,賦值給tid從頭判斷。

所以可見(jiàn)性是,只有當(dāng)?shù)谝淮巫x之前提交的修改和自己的修改可見(jiàn),其他的均不可見(jiàn)。

代碼實(shí)現(xiàn)部分

在storage/innobase/include/read0types.h中

// Friend declaration

class MVCC;

/** Read view lists the trx ids of those transactions for which a consistent

read should not see the modifications to the database. */

...

class ReadView {

...

private:

// Prevent copying

ids_t(const ids_t&);

ids_t& operator=(const ids_t&);

private:

/** Memory for the array */

value_type* m_ptr;

/** Number of active elements in the array */

ulint m_size;

/** Size of m_ptr in elements */

ulint m_reserved;

friend class ReadView;

};

public:

ReadView();

~ReadView();

/** Check whether transaction id is valid.

@param[in] id transaction id to check

@param[in] name table name */

static void check_trx_id_sanity(

trx_id_t id,

const table_name_t& name);

// 判斷一個(gè)修改是否可見(jiàn)

/** Check whether the changes by id are visible.

@param[in] id transaction id to check against the view

@param[in] name table name

@return whether the view sees the modifications of id. */

bool changes_visible(

trx_id_t id,

const table_name_t& name) const

MY_ATTRIBUTE((warn_unused_result))

{

ut_ad(id > 0);

if (id < m_up_limit_id || id == m_creator_trx_id) {

return(true);

}

check_trx_id_sanity(id, name);

if (id >= m_low_limit_id) {

return(false);

} else if (m_ids.empty()) {

return(true);

}

const ids_t::value_type* p = m_ids.data();

return(!std::binary_search(p, p + m_ids.size(), id));

}

private:

// Disable copying

ReadView(const ReadView&);

ReadView& operator=(const ReadView&);

private:

// 活動(dòng)事務(wù)中的id的最大

/** The read should not see any transaction with trx id >= this

value. In other words, this is the "high water mark". */

trx_id_t m_low_limit_id;

// 活動(dòng)事務(wù)id的最小值

/** The read should see all trx ids which are strictly

smaller (

low water mark". */

//

trx_id_t m_up_limit_id;

/** trx id of creating transaction, set to TRX_ID_MAX for free

views. */

trx_id_t m_creator_trx_id;

/** Set of RW transactions that was active when this snapshot

was taken */

ids_t m_ids;

/** The view does not need to see the undo logs for transactions

whose transaction number is strictly smaller (

they can be removed in purge if not needed by other views */

trx_id_t m_low_limit_no;

/** AC-NL-RO transaction view that has been "closed". */

bool m_closed;

typedef UT_LIST_NODE_T(ReadView) node_t;

/** List of read views in trx_sys */

byte pad1[64 - sizeof(node_t)];

node_t m_view_list;

};

Undo log刪除

undo log在沒(méi)有活動(dòng)事務(wù)依賴(lài)(用于consistent read或回滾)便可以清楚,innodb 中存在后臺(tái)purge 線程進(jìn)行后臺(tái)輪詢(xún)刪除undo log。

Current Read snapshot read

REPEATABLE READ隔離級(jí)別下普通的讀操作即select都不加鎖,使用MVCC進(jìn)行一致性讀取,這種讀取又叫做snapshot read。

而update, insert, delete, select … for update, select … lock in share mode都會(huì)進(jìn)行加鎖,并且讀取的是當(dāng)前版本,也就是READ COMMITTED讀的效果。innodb-locks-set.html中對(duì)各種操作會(huì)進(jìn)行的鎖操作有詳細(xì)的說(shuō)明,這里我簡(jiǎn)單總結(jié)下。

InnoDB中加鎖的方法是鎖住對(duì)應(yīng)的索引,一個(gè)操作進(jìn)行前會(huì)選擇一個(gè)索引進(jìn)行掃描,掃描到一行后加上對(duì)應(yīng)的鎖然后返回給上層然后繼續(xù)掃描。InnoDB支持行級(jí)鎖(record lock),上述需要加鎖的操作中,除了select … lock in share mode 是加shared lock(共享鎖或讀鎖)外其他操作都加的是exclusive lock(即排他鎖或?qū)戞i)。在加行級(jí)鎖前,會(huì)對(duì)表加一個(gè)intention lock,即意向鎖,意向所是表級(jí)鎖,不會(huì)和行級(jí)鎖沖突,主要用途是表明一個(gè)要加行級(jí)鎖或正在加鎖的操作。

另外InnoDB種除了record lock外還有一種gap lock,即鎖住兩個(gè)記錄間的間隙,防止其他事務(wù)插入數(shù)據(jù),用于防止幻讀。當(dāng)索引是主鍵索引或唯一索引時(shí),不需要加gap lock。當(dāng)索引不是唯一索引時(shí),需要對(duì)索引數(shù)據(jù)和索引前的gap加鎖,這種方式叫做next-key locking。

另外在插入數(shù)據(jù)時(shí),還需要提前最插入行的前面部分加上insert intention lock, 即插入意向鎖,插入意向鎖之間不會(huì)沖突,會(huì)和gap鎖沖突導(dǎo)致等待。當(dāng)插入時(shí)遇到duplicated key錯(cuò)誤時(shí),會(huì)在要插入的行上加上share lock。

參考

  • https://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html
  • http://hedengcheng.com/
  • MySQL技術(shù)內(nèi)幕
  • http://www.postgres.cn/downfiles/pg2016conf_day2_s1_pm3.pdf
  • https://dev.mysql.com/doc/refman/5.7/en/source-installation.html
  • https://blog.jcole.us/2014/04/16/the-basics-of-the-innodb-undo-logging-and-history-system/
  • http://www.cnblogs.com/chenpingzhao/p/5065316.html

總結(jié)

以上是生活随笔為你收集整理的window.open 实现session隔离_InnoDB存储引擎MVCC实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

主站蜘蛛池模板: 成年精品 | heyzo朝桐光一区二区 | 亚洲精选一区二区 | 国产精品久久久久久精 | 久久天天东北熟女毛茸茸 | 91porny九色91啦中文 | 一区二区三区国产精品视频 | 国产色在线视频 | 青青在线 | 中日韩免费毛片 | 蜜桃视频免费网站 | 性开放耄耋老妇hd | 综合久久久久久久久久久 | 久久一区二区三区视频 | 另类视频在线观看+1080p | 不卡视频在线播放 | 国产污网站| 妺妺窝人体色www在线下载 | 国产成人精品一区二区在线观看 | 污污网站在线看 | 午夜三级视频 | 天堂网中文在线 | 伊人色婷婷 | 波多野结衣三级视频 | 婷婷综合影院 | 日批视频免费看 | 午夜精品99 | 中文字幕无线精品亚洲乱码一区 | 日韩新片王网 | 精品一区二区三区免费毛片 | 久草免费在线色站 | 亚洲a精品 | 国产精品久久久久久久久久久久午夜片 | www.五月婷婷.com | 熟女av一区二区三区 | 国语对白av | 天堂资源av | 成年人在线视频 | 午夜视频福利在线 | 亚洲热av| 手机av在线| 亚洲视频网站在线 | 欧美激情国产精品 | 林由奈在线观看 | 狠狠一区二区 | 男生女生插插插 | 午夜啊啊啊 | 成人免费视频网站在线观看 | 26uuu精品一区二区在线观看 | 中文字幕一区二区免费 | 国产一区福利 | 欧洲一区二区三区 | 91啦中文 | 国产三级国产精品国产国在线观看 | 日韩av在线第一页 | 亚洲av日韩av高潮潮喷无码 | 午夜激情在线 | 97播播| 日韩在线视频观看 | 男人操女人下面 | 亚洲麻豆一区二区三区 | 四虎免费影视 | 精品久久久久一区二区 | 成人做爰69片免费观看 | 蜜桃av噜噜 | 亚洲视频网址 | 成人精品一区二区三区在线 | 国产成人精品女人久久久 | 日韩美女爱爱 | 中文日韩欧美 | 91精品国产色综合久久不卡粉嫩 | 免费黄视频在线观看 | 99re久久| 亚洲欧美色图 | 国产三区四区视频 | 看黄色的网站 | 午夜爱爱免费视频 | 毛片大全免费看 | www.黄色av | 亚洲欧美日韩在线 | 亚洲一二区 | 思思精品视频 | 91久久久久久久久久久久久 | 天天干天天操天天插 | 少妇高潮迭起 | 亚欧在线视频 | 狠狠躁18三区二区一区传媒剧情 | 特级黄色大片 | 少妇久久精品 | 日b影院 | 一本免费视频 | 高清免费av| 午夜刺激视频 | 老太婆av | 91视频污在线观看 | 岛国大片在线免费观看 | 午夜久久久久久久久久影院 | 精品国产乱码久久久久久1区二区 | 91看片在线看 |