偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

數(shù)據(jù)庫 MySQL
在Innodb中,每次開啟一個事務(wù)時,都會為該session分配一個事務(wù)對象。今天主要分享下Innodb事務(wù)系統(tǒng)的一些優(yōu)化相關(guān),以下基于mysql 5.7。

今天主要分享下Innodb事務(wù)系統(tǒng)的一些優(yōu)化相關(guān),以下基于mysql 5.7。

一、Innodb中的事務(wù)、視圖、多版本

1. 事務(wù)

在Innodb中,每次開啟一個事務(wù)時,都會為該session分配一個事務(wù)對象。而為了對全局所有的事務(wù)進行控制和協(xié)調(diào),有一個全局對象trx_sys,對trx_sys相關(guān)成員的操作需要trx_sys->mutex鎖。

mysql數(shù)據(jù)庫遵循的是兩段鎖協(xié)議,將事務(wù)分成兩個階段,加鎖階段和解鎖階段(所以叫兩段鎖)

  • 加鎖階段:在該階段可以進行加鎖操作。在對任何數(shù)據(jù)進行讀操作之前要申請并獲得S鎖(共享鎖,其它事務(wù)可以繼續(xù)加共享鎖,但不能加排它鎖),在進行寫操作之前要申請并獲得X鎖(排它鎖,其它事務(wù)不能再獲得任何鎖)。加鎖不成功,則事務(wù)進入等待狀態(tài),直到加鎖成功才繼續(xù)執(zhí)行。
  • 解鎖階段:當(dāng)事務(wù)釋放了一個封鎖以后,事務(wù)進入解鎖階段,在該階段只能進行解鎖操作不能再進行加鎖操作。

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

2. 視圖

Innodb使用一種稱做ReadView(視圖)的對象來判斷事務(wù)的可見性(也就是ACID中的隔離性)。根據(jù)可見性原則,某個新開啟的事務(wù)不應(yīng)該看到其他未提交的事務(wù)。 Innodb在執(zhí)行一個SELECT或者顯式開啟START TRANSACTION WITH CONSISTENT SNAPSHOT (后者只應(yīng)用于REPEATABLE-READ隔離級別) 會創(chuàng)建一個視圖對象。對于RR隔離級別,視圖的生命周期到事務(wù)提交結(jié)束,對于RC隔離級別,則每條查詢開始時重分配事務(wù)。

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

通常一個視圖中包含創(chuàng)建視圖的事務(wù)ID,以及在創(chuàng)建視圖時活躍的事務(wù)ID數(shù)組。例如,當(dāng)開啟一個視圖時,當(dāng)前事務(wù)的事務(wù)ID為5, 事務(wù)鏈表上活躍事務(wù)ID為{2,5,6,9,12},那么就會把{2,6,9,12}存儲到當(dāng)前的視圖中(5是當(dāng)前事務(wù)的ID,不記錄到視圖中),{2,6,9,12}對應(yīng)的事務(wù)所做的修改對當(dāng)前事務(wù)而言都是不可見的,小于2的事務(wù)ID對當(dāng)前事務(wù)都是可見的,大于12的事務(wù)ID對當(dāng)前事務(wù)是不可見的。

那么如何判斷可見性呢?

InnoDB表數(shù)據(jù)的組織方式為主鍵聚簇索引。由于采用索引組織表結(jié)構(gòu),記錄的ROWID是可變的(索引頁分裂的時候,Structure Modification Operation,SMO),因此二級索引中采用的是(索引鍵值, 主鍵鍵值)的組合來唯一確定一條記錄。無論是聚簇索引,還是二級索引,其每條記錄都包含了一個DELETED BIT位,用于標(biāo)識該記錄是否是刪除記錄。除此之外,聚簇索引記錄還有兩個系統(tǒng)列:DATA_TRX_ID,DATA_ROLL_PTR。DATA _TRX_ID表示產(chǎn)生當(dāng)前記錄項的事務(wù)ID;DATA _ROLL_PTR指向當(dāng)前記錄項的undo信息。

聚簇索引行結(jié)構(gòu)(與多版本一致讀有關(guān)的部分,DELETED BIT省略):

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

二級索引行結(jié)構(gòu):

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

從聚簇索引行結(jié)構(gòu),與二級索引行結(jié)構(gòu)可以看出,聚簇索引中包含版本信息(事務(wù)號+回滾指針),二級索引不包含版本信息。

對于聚集索引,每次修改記錄時,都會在記錄中保存當(dāng)前的事務(wù)ID,同時舊版本記錄存儲在UNDO中;對于二級索引,則在二級索引頁中存儲了更新當(dāng)前頁的最大事務(wù)ID,如果該事務(wù)ID大于readview->up_limit_id(對于上例,up_limit_id值為2),那么就需要回聚集索引判斷記錄可見性;如果小于2, 那么總是可見的,可以直接讀取。

3. 多版本(MVCC)

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

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

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

說明:

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

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

MySQL性能優(yōu)化之Innodb事務(wù)系統(tǒng),值得收藏

(1) SELECT

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

  • 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ù)開始之前未被刪除。

(2) INSERT

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

(3) DELETE

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

(4) UPDATE

InnoDB為插入一行新記錄,保存當(dāng)前系統(tǒng)版本號作為行版本號,同時保存當(dāng)前系統(tǒng)版本號到原來的行作為行刪除標(biāo)識。

Innodb的多版本數(shù)據(jù)使用UNDO來維護的,例如聚集索引記錄(1) =>(2)=>(3),從1更新成2,再更新成3,就會產(chǎn)生兩條undo記錄。

二、Innodb事務(wù)系統(tǒng)優(yōu)化

在MySQL 5.7版本里,針對性的對事務(wù)系統(tǒng)做了比較深入的優(yōu)化,主要解決了下面幾個問題。

1. 視圖對象的創(chuàng)建需要trx_sys->mutex鎖保護

trx_sys->mutex是事務(wù)系統(tǒng)最核心的全局鎖對象,持有該鎖進行的操作都不應(yīng)該耗時過長。對于read view對象,完全可以將其緩存下來重復(fù)使用。這樣就避免了持有鎖分配視圖內(nèi)存。

因此在MySQL 5.7版本中,實例啟動時就分配1024個視圖對象;同時維護兩個鏈表,一個是已使用的視圖鏈表,一個是空閑的視圖鏈表;當(dāng)需要分配新的視圖時,總是從空閑視圖鏈表中分配,如果沒有,再新分配一個。

2. 視圖對象中保存全局事務(wù)ID時,需要掃描事務(wù)鏈表

為了判斷事務(wù)視圖的可見性,在打開一個視圖時需要拷貝當(dāng)時活躍的事務(wù)ID。

在5.7中,事務(wù)系統(tǒng)維持了一個全局事務(wù)ID數(shù)組,每個活躍讀寫事務(wù)的ID都被加入到其中,在事務(wù)提交時從其中刪除,這樣打開視圖時只需要使用memcpy 拷貝該數(shù)組即可,無需遍歷鏈表。在讀寫鏈表較長(高并發(fā)下)的場景,該優(yōu)化可以顯著的提升性能。

3. 用戶需要顯式開啟只讀事務(wù),才會放入只讀事務(wù)鏈表

mysql5.7將只讀事務(wù)鏈表從其中徹底移除了,取而代之的是,所有事務(wù)都以只讀模式打開。

例如如下事務(wù)序列:

  1. BEGIN; 
  2. SELECT; //事務(wù)開始,不分配事務(wù)ID,不分配回滾段; 
  3. UPDATE; //分配事務(wù)ID并插入全局事務(wù)數(shù)組和事務(wù)對象集合中,分配回滾段; 
  4. COMMIT; 

而對于BEGIN;SELECT;SELECT;COMMIT這樣的序列,整個事務(wù)周期既不分配事務(wù)ID,也不分配回滾段。

4. 隱式鎖轉(zhuǎn)換為顯式鎖的開銷

Innodb對于類似INSERT操作,采用的是隱式鎖的方式,隱式鎖不是鎖,只是一種稱呼而已,只有在需要的時候,才會轉(zhuǎn)換為顯式鎖。例如如下:

  1. Session 1: BEING; INSERT INTO t1(pk, val) VALUES (1,2); //不創(chuàng)建鎖對象 
  2. Session 2: UPDATE t1 SET valval=val+1 WHERE pk=1; //創(chuàng)建兩個鎖對象,一個是為session1創(chuàng)建一個記錄鎖對象,另外一個是給自己創(chuàng)建一個等待類型的記錄鎖對象,然后session2加入鎖等待隊列。 

在Session 2中為Session1創(chuàng)建鎖對象的過程即是所謂的隱式鎖向顯式鎖轉(zhuǎn)換。 當(dāng)session2掃描到session 1插入的記錄時,發(fā)現(xiàn)session 1的事務(wù)依然活躍,就會進入轉(zhuǎn)換邏輯。

在5.6版本中,其轉(zhuǎn)換過程如下:

  • 持有l(wèi)ock_sys->mutex
  • 2持有trx_sys->mutex;根據(jù)事務(wù)ID,掃描讀寫事務(wù)鏈表,找到對應(yīng)的事務(wù)對象;釋放trx_sys->mutex;
  • 創(chuàng)建顯式鎖對象
  • 釋放lock_sys->mutex

可以看到,在該操作的過程中,全程持有l(wèi)ock_sys->mutex,持有鎖的原因是防止事務(wù)提交掉。當(dāng)讀寫事務(wù)鏈表非常長時(例如高并發(fā)寫入時),這種開銷將是不可接受的。

在5.7版本中,上述邏輯則優(yōu)化成:

(1)  持有trx_sys->mutex

  • 根據(jù)事務(wù)ID找到對應(yīng)的事務(wù)對象(直接查找trx_sys->rw_trx_set,其保存了trx_id和事務(wù)對象的映射關(guān)系,因此無需掃描讀寫事務(wù)鏈表)
  • 增加事務(wù)對象引用計數(shù)(++trx->n_ref)
  • 釋放trx_sys->mutex

(2) 持有l(wèi)ock_sys->mutex;

  • 創(chuàng)建顯式鎖對象;
  • 釋放lock_sys->mutex;

(3) 遞減事務(wù)對象引用計數(shù)

在事務(wù)commit,釋放記錄鎖前,會先判斷引用記錄數(shù)是否為0,如果不為0,表示正有其他事務(wù)為其轉(zhuǎn)換顯式鎖,這時候需要等待,直到計數(shù)為0,才能進入釋放事務(wù)記錄鎖階段。

總的來說,該優(yōu)化減少了隱式鎖轉(zhuǎn)換時持有LOCK_sys->mutex的時間,從而提升性能。

責(zé)任編輯:趙寧寧 來源: 今日頭條
相關(guān)推薦

2023-11-15 16:35:31

SQL數(shù)據(jù)庫

2020-03-27 15:40:10

MySQL索引數(shù)據(jù)庫

2019-02-26 09:14:02

SSD狀態(tài)監(jiān)控

2011-06-14 14:17:23

性能優(yōu)化系統(tǒng)層次

2019-02-26 15:17:15

工具性能數(shù)據(jù)

2019-12-02 08:58:09

SQL腳本語言MySQL

2019-08-05 09:19:45

PG事務(wù)隔離級別數(shù)據(jù)庫

2019-09-26 08:59:39

DockerGoogle軟件

2019-07-29 17:15:35

MySQL操作系統(tǒng)數(shù)據(jù)庫

2019-10-22 18:00:00

MySQL基礎(chǔ)入門數(shù)據(jù)庫

2022-02-08 18:53:12

SpringBoot性能優(yōu)化

2011-03-11 15:53:02

LAMP優(yōu)化

2015-11-10 16:55:00

性能IO子系統(tǒng)Linux

2021-07-29 14:20:34

網(wǎng)絡(luò)優(yōu)化移動互聯(lián)網(wǎng)數(shù)據(jù)存儲

2022-02-16 14:10:51

服務(wù)器性能優(yōu)化Linux

2021-11-29 11:13:45

服務(wù)器網(wǎng)絡(luò)性能

2020-05-27 11:55:47

Oracle SQL性能優(yōu)化數(shù)據(jù)庫

2018-06-01 16:24:29

數(shù)據(jù)庫MySQL Innod阻塞事務(wù)

2024-01-18 09:43:11

MySQL數(shù)據(jù)庫

2024-07-31 08:33:17

點贊
收藏

51CTO技術(shù)棧公眾號