成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL性能優化之Innodb事務系統,值得收藏

數據庫 MySQL
在Innodb中,每次開啟一個事務時,都會為該session分配一個事務對象。今天主要分享下Innodb事務系統的一些優化相關,以下基于mysql 5.7。

今天主要分享下Innodb事務系統的一些優化相關,以下基于mysql 5.7。

一、Innodb中的事務、視圖、多版本

1. 事務

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

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

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

MySQL性能優化之Innodb事務系統,值得收藏

2. 視圖

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

MySQL性能優化之Innodb事務系統,值得收藏

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

那么如何判斷可見性呢?

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

聚簇索引行結構(與多版本一致讀有關的部分,DELETED BIT省略):

MySQL性能優化之Innodb事務系統,值得收藏

二級索引行結構:

MySQL性能優化之Innodb事務系統,值得收藏

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

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

3. 多版本(MVCC)

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

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

MySQL性能優化之Innodb事務系統,值得收藏

說明:

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

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

MySQL性能優化之Innodb事務系統,值得收藏

(1) SELECT

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

  • InnoDB只查找版本(DB_TRX_ID)早于當前事務版本的數據行(行的系統版本號<=事務的系統版本號,這樣可以確保數據行要么是在開始之前已經存在了,要么是事務自身插入或修改過的)
  • 行的刪除版本號(DB_ROLL_PTR)要么未定義(未更新過),要么大于當前事務版本號(在當前事務開始之后更新的)。這樣可以確保事務讀取到的行,在事務開始之前未被刪除。

(2) INSERT

InnoDB為新插入的每一行保存當前系統版本號作為行版本號

(3) DELETE

InnoDB為刪除的每一行保存當前的系統版本號作為行刪除標識

(4) UPDATE

InnoDB為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。

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

二、Innodb事務系統優化

在MySQL 5.7版本里,針對性的對事務系統做了比較深入的優化,主要解決了下面幾個問題。

1. 視圖對象的創建需要trx_sys->mutex鎖保護

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

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

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

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

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

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

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

例如如下事務序列:

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

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

4. 隱式鎖轉換為顯式鎖的開銷

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

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

在Session 2中為Session1創建鎖對象的過程即是所謂的隱式鎖向顯式鎖轉換。 當session2掃描到session 1插入的記錄時,發現session 1的事務依然活躍,就會進入轉換邏輯。

在5.6版本中,其轉換過程如下:

  • 持有lock_sys->mutex
  • 2持有trx_sys->mutex;根據事務ID,掃描讀寫事務鏈表,找到對應的事務對象;釋放trx_sys->mutex;
  • 創建顯式鎖對象
  • 釋放lock_sys->mutex

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

在5.7版本中,上述邏輯則優化成:

(1)  持有trx_sys->mutex

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

(2) 持有lock_sys->mutex;

  • 創建顯式鎖對象;
  • 釋放lock_sys->mutex;

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

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

總的來說,該優化減少了隱式鎖轉換時持有LOCK_sys->mutex的時間,從而提升性能。

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2023-11-15 16:35:31

SQL數據庫

2020-03-27 15:40:10

MySQL索引數據庫

2019-02-26 09:14:02

SSD狀態監控

2011-06-14 14:17:23

性能優化系統層次

2019-02-26 15:17:15

工具性能數據

2019-12-02 08:58:09

SQL腳本語言MySQL

2019-08-05 09:19:45

PG事務隔離級別數據庫

2019-09-26 08:59:39

DockerGoogle軟件

2022-02-08 18:53:12

SpringBoot性能優化

2019-10-22 18:00:00

MySQL基礎入門數據庫

2019-07-29 17:15:35

MySQL操作系統數據庫

2011-03-11 15:53:02

LAMP優化

2015-11-10 16:55:00

性能IO子系統Linux

2021-07-29 14:20:34

網絡優化移動互聯網數據存儲

2021-11-29 11:13:45

服務器網絡性能

2020-05-27 11:55:47

Oracle SQL性能優化數據庫

2022-02-16 14:10:51

服務器性能優化Linux

2024-07-31 08:33:17

2024-01-18 09:43:11

MySQL數據庫

2018-01-09 16:56:32

數據庫OracleSQL優化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精彩视频 | 久久人人国产 | 亚洲成人免费在线观看 | 国产成人精品免高潮在线观看 | 精品精品| 欧美一区二区三区在线视频 | 一区二区在线看 | 亚洲免费人成在线视频观看 | 亚洲欧美综合精品久久成人 | 国产专区视频 | 欧美日韩在线免费观看 | 国产精品毛片无码 | 欧美精品一区二区三区四区 在线 | 精品一区二区不卡 | 色综合天天网 | 伦理二区| 亚洲欧洲精品成人久久奇米网 | 国产在线不卡 | 亚洲精品在线免费 | 亚洲综合久久久 | 欧美一区二区黄 | 精品欧美一区二区三区免费观看 | 欧美成人精品一区二区三区 | 亚洲视频区| 欧美在线一区二区三区 | 成人欧美一区二区三区色青冈 | 一区二区三区高清不卡 | 色婷婷九月 | 国产精品99久久久久久www | 中文字幕一区在线观看视频 | caoporn视频在线| 国产人免费人成免费视频 | 国产视频亚洲视频 | 成人午夜网站 | 成人亚洲一区 | 一区二区三区小视频 | 日韩一区二区在线免费观看 | 久久免费精品视频 | 久久免费高清 | 卡通动漫第一页 | 成人在线免费观看视频 |