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

MySQL中的隱藏列的具體查看

 更新時(shí)間:2021年09月02日 15:03:00   作者:碼農(nóng)參上  
mysql中存在一些隱藏列,例如行標(biāo)識(shí)、事務(wù)ID、回滾指針等,不知道大家是否和我一樣好奇過,要怎樣才能實(shí)際地看到這些隱藏列的值呢,感興趣的可以了解一下

在介紹mysql的多版本并發(fā)控制mvcc的過程中,我們提到過mysql中存在一些隱藏列,例如行標(biāo)識(shí)、事務(wù)ID、回滾指針等,不知道大家是否和我一樣好奇過,要怎樣才能實(shí)際地看到這些隱藏列的值呢?

本文我們就來重點(diǎn)討論一下諸多隱藏列中的行標(biāo)識(shí)DB_ROW_ID,實(shí)際上,將行標(biāo)識(shí)稱為隱藏列并不準(zhǔn)確,因?yàn)樗⒉皇且粋€(gè)真實(shí)存在的列,DB_ROW_ID實(shí)際上是一個(gè)非空唯一列的別名。在撥開它的神秘面紗之前,我們看一下官方文檔的說明:

If a table has a PRIMARY KEY or UNIQUE NOT NULL index that consists of a single column that has an integer type, you can use _rowid to refer to the indexed column in SELECT statements

簡(jiǎn)單翻譯一下,如果在表中存在主鍵或非空唯一索引,并且僅由一個(gè)整數(shù)類型的列構(gòu)成,那么就可以使用SELECT語句直接查詢_rowid,并且這個(gè)_rowid的值會(huì)引用該索引列的值。

著重看一下文檔中提到的幾個(gè)關(guān)鍵字,主鍵、唯一索引、非空、單獨(dú)一列、數(shù)值類型,接下來我們就要從這些角度入手,探究一下神秘的隱藏字段_rowid。

1、存在主鍵

先看設(shè)置了主鍵且是數(shù)值類型的情況,使用下面的語句建表:

CREATE TABLE `table1` (
  `id` bigint(20) NOT NULL PRIMARY KEY ,
  `name` varchar(32) DEFAULT NULL
) ENGINE=InnoDB;

插入三條測(cè)試數(shù)據(jù)后,執(zhí)行下面的查詢語句,在select查詢語句中直接查詢_rowid

select *,_rowid from table1

查看執(zhí)行結(jié)果,_rowid可以被正常查詢:

可以看到在設(shè)置了主鍵,并且主鍵字段是數(shù)值類型的情況下,_rowid直接引用了主鍵字段的值。對(duì)于這種可以被select語句查詢到的的情況,可以將其稱為顯式的rowid。

回顧一下前面提到的文檔中的幾個(gè)關(guān)鍵字,分別對(duì)其進(jìn)行分析。由于主鍵必定是非空字段,下面來看一下主鍵是非數(shù)值類型字段的情況,建表如下:

CREATE TABLE `table2` (
  `id` varchar(20) NOT NULL PRIMARY KEY ,
  `name` varchar(32) DEFAULT NULL
) ENGINE=InnoDB;

table2執(zhí)行上面相同的查詢,結(jié)果報(bào)錯(cuò)無法查詢_rowid,也就證明了如果主鍵字段是非數(shù)值類型,那么將無法直接查詢_rowid。

2、無主鍵,存在唯一索引

上面對(duì)兩種類型的主鍵進(jìn)行了測(cè)試后,接下來我們看一下當(dāng)表中沒有主鍵、但存在唯一索引的情況。首先測(cè)試非空唯一索引加在數(shù)值類型字段的情況,建表如下:

CREATE TABLE `table3` (
  `id` bigint(20) NOT NULL UNIQUE KEY,
  `name` varchar(32)
) ENGINE=InnoDB;

查詢可以正常執(zhí)行,并且_rowid引用了唯一索引所在列的值:

唯一索引與主鍵不同的是,唯一索引所在的字段可以為NULL。在上面的table3中,在唯一索引所在的列上添加了NOT NULL非空約束,如果我們把這個(gè)非空約束刪除掉,還能顯式地查詢到_rowid嗎?下面再創(chuàng)建一個(gè)表,不同是在唯一索引所在的列上,不添加非空約束:

CREATE TABLE `table4` (
  `id` bigint(20) UNIQUE KEY,
  `name` varchar(32)
) ENGINE=InnoDB;

執(zhí)行查詢語句,在這種情況下,無法顯式地查詢到_rowid

和主鍵類似的,我們?cè)賹?duì)唯一索引被加在非數(shù)值類型的字段的情況進(jìn)行測(cè)試。下面在建表時(shí)將唯一索引添加在字符類型的字段上,并添加非空約束:

CREATE TABLE `table5` (
  `id` bigint(20),
  `name` varchar(32) NOT NULL UNIQUE KEY
) ENGINE=InnoDB;

同樣無法顯示的查詢到_rowid

針對(duì)上面三種情況的測(cè)試結(jié)果,可以得出結(jié)論,當(dāng)沒有主鍵、但存在唯一索引的情況下,只有該唯一索引被添加在數(shù)值類型的字段上,且該字段添加了非空約束時(shí),才能夠顯式地查詢到_rowid,并且_rowid引用了這個(gè)唯一索引字段的值。

3、存在聯(lián)合主鍵或聯(lián)合唯一索引

在上面的測(cè)試中,我們都是將主鍵或唯一索引作用在單獨(dú)的一列上,那么如果使用了聯(lián)合主鍵或聯(lián)合唯一索引時(shí),結(jié)果會(huì)如何呢?還是先看一下官方文檔中的說明:

_rowid refers to the PRIMARY KEY column if there is a PRIMARY KEY consisting of a single integer column. If there is a PRIMARY KEY but it does not consist of a single integer column, _rowid cannot be used.

簡(jiǎn)單來說就是,如果主鍵存在、且僅由數(shù)值類型的一列構(gòu)成,那么_rowid的值會(huì)引用主鍵。如果主鍵是由多列構(gòu)成,那么_rowid將不可用。

根據(jù)這一描述,我們測(cè)試一下聯(lián)合主鍵的情況,下面將兩列數(shù)值類型字段作為聯(lián)合主鍵建表:

CREATE TABLE `table6` (
  `id` bigint(20) NOT NULL,
  `no` bigint(20) NOT NULL,
  `name` varchar(32),
  PRIMARY KEY(`id`,`no`)
) ENGINE=InnoDB;

執(zhí)行結(jié)果無法顯示的查詢到_rowid

同樣,這一理論也可以作用于唯一索引,如果非空唯一索引不是由單獨(dú)一列構(gòu)成,那么也無法直接查詢得到_rowid。這一測(cè)試過程省略,有興趣的小伙伴可以自己動(dòng)手試試。

4、存在多個(gè)唯一索引

在mysql中,每張表只能存在一個(gè)主鍵,但是可以存在多個(gè)唯一索引。那么如果同時(shí)存在多個(gè)符合規(guī)則的唯一索引,會(huì)引用哪個(gè)作為_rowid的值呢?老規(guī)矩,還是看官方文檔的解答:

Otherwise, _rowid refers to the column in the first UNIQUE NOT NULL index if that index consists of a single integer column. If the first UNIQUE NOT NULL index does not consist of a single integer column, _rowid cannot be used.

簡(jiǎn)單翻譯一下,如果表中的第一個(gè)非空唯一索引僅由一個(gè)整數(shù)類型字段構(gòu)成,那么_rowid會(huì)引用這個(gè)字段的值。否則,如果第一個(gè)非空唯一索引不滿足這種情況,那么_rowid將不可用。

在下面的表中,創(chuàng)建兩個(gè)都符合規(guī)則的唯一索引:

CREATE TABLE `table8_2` (
  `id` bigint(20) NOT NULL,
  `no` bigint(20) NOT NULL,
  `name` varchar(32),
  UNIQUE KEY(no),
  UNIQUE KEY(id)
) ENGINE=InnoDB;

看一下執(zhí)行查詢語句的結(jié)果:

可以看到_rowid的值與no這一列的值相同,證明了_rowid會(huì)嚴(yán)格地選取第一個(gè)創(chuàng)建的唯一索引作為它的引用。

那么,如果表中創(chuàng)建的第一個(gè)唯一索引不符合_rowid的引用規(guī)則,第二個(gè)唯一索引滿足規(guī)則,這種情況下,_rowid可以被顯示地查詢嗎?針對(duì)這種情況我們建表如下,表中的第一個(gè)索引是聯(lián)合唯一索引,第二個(gè)索引才是單列的唯一索引情況,再來進(jìn)行一下測(cè)試:

CREATE TABLE `table9` (
  `id` bigint(20) NOT NULL,
  `no` bigint(20) NOT NULL,
  `name` varchar(32),
  UNIQUE KEY `index1`(`id`,`no`),
  UNIQUE KEY `index2`(`id`)
) ENGINE=InnoDB;

進(jìn)行查詢,可以看到雖然存在一個(gè)單列的非空唯一索引,但是因?yàn)轫樞蜻x取的第一個(gè)不滿足要求,因此仍然不能直接查詢_rowid

如果將上面創(chuàng)建唯一索引的語句順序調(diào)換,那么將可以正常顯式的查詢到_rowid。

5、同時(shí)存在主鍵與唯一索引

從上面的例子中,可以看到唯一索引的定義順序會(huì)決定將哪一個(gè)索引應(yīng)用_rowid,那么當(dāng)同時(shí)存在主鍵和唯一索引時(shí),定義順序會(huì)對(duì)其引用造成影響嗎?

按照下面的語句創(chuàng)建兩個(gè)表,只有創(chuàng)建主鍵和唯一索引的順序不同:

CREATE TABLE `table11` (
  `id` bigint(20) NOT NULL,
  `no` bigint(20) NOT NULL,
  PRIMARY KEY(id),
  UNIQUE KEY(no)
) ENGINE=InnoDB;

CREATE TABLE `table12` (
  `id` bigint(20) NOT NULL,
  `no` bigint(20) NOT NULL,
  UNIQUE KEY(id),
  PRIMARY KEY(no)
) ENGINE=InnoDB;

查看運(yùn)行結(jié)果:

可以得出結(jié)論,當(dāng)同時(shí)存在符合條件的主鍵和唯一索引時(shí),無論創(chuàng)建順序如何,_rowid都會(huì)優(yōu)先引用主鍵字段的值。

6、無符合條件的主鍵與唯一索引

上面,我們把能夠直接通過select語句查詢到的稱為顯式的_rowid,在其他情況下雖然_rowid不能被顯式查詢,但是它也是一直存在的,這種情況我們可以將其稱為隱式的_rowid。

實(shí)際上,innoDB在沒有默認(rèn)主鍵的情況下會(huì)生成一個(gè)6字節(jié)長(zhǎng)度的無符號(hào)數(shù)作為自動(dòng)增長(zhǎng)的_rowid,因此最大為2^48-1,到達(dá)最大值后會(huì)從0開始計(jì)算。下面,我們創(chuàng)建一個(gè)沒有主鍵與唯一索引的表,在這張表的基礎(chǔ)上,探究一下隱式的_rowid。

CREATE TABLE `table10` (
  `id` bigint(20),
  `name` varchar(32)
) ENGINE=InnoDB;

首先,我們需要先查找到mysql的進(jìn)程pid

ps -ef | grep mysqld

可以看到,mysql的進(jìn)程pid是2068:

在開始動(dòng)手前,還需要做一點(diǎn)鋪墊, 在innoDB中其實(shí)維護(hù)了一個(gè)全局變量dictsys.row_id,沒有定義主鍵的表都會(huì)共享使用這個(gè)row_id,在插入數(shù)據(jù)時(shí)會(huì)把這個(gè)全局row_id當(dāng)作自己的主鍵,然后再將這個(gè)全局變量加 1。

接下來我們需要用到gdb調(diào)試的相關(guān)技術(shù),gdb是一個(gè)在Linux下的調(diào)試工具,可以用來調(diào)試可執(zhí)行文件。在服務(wù)器上,先通過yum install gdb安裝,安裝完成后,通過下面的gdb命令 把 row_id 修改為 1:

gdb -p 2068 -ex 'p dict_sys->row_id=1' -batch

命令執(zhí)行結(jié)果:

在空表中插入3行數(shù)據(jù):

INSERT INTO table10 VALUES (100000001, 'Hydra');
INSERT INTO table10 VALUES (100000002, 'Trunks');
INSERT INTO table10 VALUES (100000003, 'Susan');

查看表中的數(shù)據(jù),此時(shí)對(duì)應(yīng)的_rowid理論上是1~3:

然后通過gdb命令把row_id改為最大值2^48,此時(shí)已超過dictsys.row_id最大值:

gdb -p 2068 -ex 'p dict_sys->row_id=281474976710656' -batch

命令執(zhí)行結(jié)果:

再向表中插入三條數(shù)據(jù):

INSERT INTO table10 VALUES (100000004, 'King');
INSERT INTO table10 VALUES (100000005, 'Queen');
INSERT INTO table10 VALUES (100000006, 'Jack');

查看表中的全部數(shù)據(jù),可以看到第一次插入的三條數(shù)據(jù)中,有兩條數(shù)據(jù)被覆蓋了:

為什么會(huì)出現(xiàn)數(shù)據(jù)覆蓋的情況呢,我們對(duì)這一結(jié)果進(jìn)行分析。首先,在第一次插入數(shù)據(jù)前_rowid為1,插入的三條數(shù)據(jù)對(duì)應(yīng)的_rowid為1、2、3。如下圖所示:

當(dāng)手動(dòng)設(shè)置_rowid為最大值后,下一次插入數(shù)據(jù)時(shí),插入的_rowid重新從0開始,因此第二次插入的三條數(shù)據(jù)的_rowid應(yīng)該為0、1、2。這時(shí)準(zhǔn)備被插入的數(shù)據(jù)如下所示:

當(dāng)出現(xiàn)相同_rowid的情況下,新插入的數(shù)據(jù)會(huì)根據(jù)_rowid覆蓋掉原有的數(shù)據(jù),過程如圖所示:

所以當(dāng)表中的主鍵或唯一索引不滿足我們前面提到的要求時(shí),innoDB使用的隱式的_rowid是存在一定風(fēng)險(xiǎn)的,雖然說2^48這個(gè)值很大,但還是有可能被用盡的,當(dāng)_rowid用盡后,之前的記錄就會(huì)被覆蓋。從這一角度也可以提醒大家,在建表時(shí)一定要?jiǎng)?chuàng)建主鍵,否則就有可能發(fā)生數(shù)據(jù)的覆蓋。

本文基于mysql 5.7.31 進(jìn)行測(cè)試

官方文檔:https://dev.mysql.com/doc/refman/5.7/en/create-index.html

到此這篇關(guān)于MySQL中的隱藏列的具體使用的文章就介紹到這了,更多相關(guān)MySQL 隱藏列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mysql源碼學(xué)習(xí)筆記 偷窺線程

    Mysql源碼學(xué)習(xí)筆記 偷窺線程

    安裝完Mysql后,使用VS打開源碼開開眼,我嘞個(gè)去,這代碼和想象中怎么差別這么大呢?
    2011-04-04
  • 淺談MySQL的性能優(yōu)化

    淺談MySQL的性能優(yōu)化

    這篇文章主要介紹了淺談MySQL的性能優(yōu)化,MySQL性能優(yōu)化是通過對(duì)數(shù)據(jù)庫(kù)的配置、查詢優(yōu)化以及索引優(yōu)化等手段提高數(shù)據(jù)庫(kù)的響應(yīng)速度和處理能力,本文從多個(gè)層面對(duì)mysql性能優(yōu)化進(jìn)行了小結(jié),需要的朋友可以參考下
    2023-08-08
  • MySQL連接被阻塞的問題分析與解決方案(從錯(cuò)誤到修復(fù))

    MySQL連接被阻塞的問題分析與解決方案(從錯(cuò)誤到修復(fù))

    在Java應(yīng)用開發(fā)中,數(shù)據(jù)庫(kù)連接是必不可少的一環(huán),然而,在使用MySQL時(shí),我們可能會(huì)遇到MySQL服務(wù)器由于檢測(cè)到過多的連接失敗,自動(dòng)阻止了來自該主機(jī)的連接請(qǐng)求,本文將深入分析該問題的原因,并提供完整的解決方案,需要的朋友可以參考下
    2025-04-04
  • MySQL回滾日志(undo?log)的作用和使用詳解

    MySQL回滾日志(undo?log)的作用和使用詳解

    undo?log是innodb引擎的一種日志,在事務(wù)的修改記錄之前,會(huì)把該記錄的原值先保存起來再做修改,以便修改過程中出錯(cuò)能夠恢復(fù)原值或者其他的事務(wù)讀取,這篇文章主要給大家介紹了關(guān)于MySQL回滾日志(undo?log)的作用和使用的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • mysql免安裝版步驟解壓后找不到密碼處理方法

    mysql免安裝版步驟解壓后找不到密碼處理方法

    這篇文章主要介紹了mysql免安裝版步驟解壓后找不到密碼處理步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 深入探尋mysql自增列導(dǎo)致主鍵重復(fù)問題的原因

    深入探尋mysql自增列導(dǎo)致主鍵重復(fù)問題的原因

    前幾天開發(fā)的同事反饋一個(gè)利用load data infile命令導(dǎo)入數(shù)據(jù)主鍵沖突的問題,分析后確定這個(gè)問題可能是mysql的一個(gè)bug,這里提出來給大家分享下。以免以后有童鞋遇到類似問題百思不得其解,難以入眠,哈哈。
    2014-08-08
  • golang實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)備份的操作方法

    golang實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)備份的操作方法

    這篇文章主要介紹了golang實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)備份的操作方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-06-06
  • mysql8.0數(shù)據(jù)庫(kù)無法被遠(yuǎn)程連接問題排查小結(jié)

    mysql8.0數(shù)據(jù)庫(kù)無法被遠(yuǎn)程連接問題排查小結(jié)

    本文主要介紹了mysql8.0數(shù)據(jù)庫(kù)無法被遠(yuǎn)程連接問題排查小結(jié)
    2024-07-07
  • mysql CPU高負(fù)載問題排查

    mysql CPU高負(fù)載問題排查

    這篇文章主要介紹了mysql CPU高負(fù)載問題排查的相關(guān)資料,幫助大家更好的理解和使用MySQL,維護(hù)數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2020-11-11
  • mysql5.7.19 安裝配置方法圖文教程(win10)

    mysql5.7.19 安裝配置方法圖文教程(win10)

    這篇文章主要為大家分享了win10下mysql 5.7.19 安裝配置方法圖文教程,感興趣的朋友可以參考一下
    2017-07-07

最新評(píng)論

丹凤县| 那坡县| 将乐县| 赞皇县| 水城县| 马尔康县| 崇义县| 合山市| 鹤庆县| 长春市| 盐城市| 宜兰市| 寻乌县| 沁水县| 长阳| 合川市| 凌源市| 和静县| 巴青县| 会昌县| 新巴尔虎右旗| 曲周县| 太和县| 福贡县| 菏泽市| 香河县| 大埔县| 天台县| 马龙县| 南汇区| 固安县| 闵行区| 阿坝县| 河北省| 资溪县| 且末县| 志丹县| 昌宁县| 隆昌县| 永州市| 布尔津县|