操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    MySQL 8.0 對數據字典進行了重構,用戶表、數據字典表、MySQL 其它系統表的元數據都統一保存到mysql 庫的數據字典表中了。

    mysql 庫中,除了、 個日志表,其它所有表的存儲引擎都是,伴隨而來的是 DDL 終于能夠支持原子操作了。

    以DROP TABLE t1, t2為例,不會出現 t1 表刪除成功,t2 表刪除失敗的情況,而是要么都刪除成功,要么都刪除失敗。

    本文我們就來聊聊 MySQL 8.0 中的數據字典表。

    本文內容基于 MySQL 8.0.29 源碼。

    1、概述

    MySQL 8.0 重構數據字典之后,廢除了 MySQL 5.7 中用于保存元數據的磁盤文件:.frm、.par、.TRN、.TRG、.isl、db.opt、.log。

    如果想要了解上面這些磁盤文件都保存了什么元數據,可以參照 MySQL 官方文檔:。

    這些文件被廢除之后,原本保存到這些文件中的元數據,都保存到數據字典表中了。

    數據字典表本身也大變樣了:

    上面 4 個數據字典表的名字也發生了變化,后面會介紹。

    2、數據字典表有哪些?

    按照官方文檔的定義,MySQL 8.0 一共有 31 張數據字典表:

    dd_properties
    innodb_ddl_log
    catalogs
    character_sets
    check_constraints
    collations
    column_statistics
    column_type_elements
    columns
    events
    foreign_key_column_usage
    foreign_keys
    index_column_usage
    index_partitions
    index_stats
    indexes
    parameter_type_elements
    parameters
    resource_groups
    routines
    schemata
    st_spatial_reference_systems
    table_partition_values
    table_partitions
    table_stats
    tables
    tablespace_files
    tablespaces
    triggers
    view_routine_usage
    view_table_usage

    上面只是簡單列出了數據字典表的表名,如果想了解每個表存放了什么內容,可以參照官方文檔:。

    默認情況下,我們是看不到數據字典表的,需要滿足以下條件才能看到:

    SET SESSION debug = '+d,skip_dd_table_access_check'

    滿足以上 2 個條件之后,執行下面這條 SQL 就可以看到所有數據字典表了:

    SELECT a.name AS db_name, b.*
    FROM mysql.schemata AS a
    INNER JOIN mysql.tables AS b ON a.id = b.schema_id
    WHERE b.schema_id = 1 AND b.hidden = 'System'
    ORDER BY b.id

    執行上面的 SQL 列出來的表有 32 個,其中ata表不屬于數據字典表。

    上面列出的數據字典表中,有 4 個需要重點介紹,因為不管是數據字典表本身,還是用戶表,都離不開這 4 個表:

    和 表不完全一樣,有 2 點需要說明:

    以下是一個測試表,圖中name是從 表中連表查詢得到的,其它都是 表的字段

    CREATE TABLE `t5` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `str1` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    `i1` int NOT NULL DEFAULT '0',
    `str2` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    `i2` int NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `idx_i1` (`i1`) USING BTREE,
    KEY `idx_str1` (`str1`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

    = 310是主鍵索引, =0的記錄是主鍵字段; =1的記錄是主鍵索引中的其它字段,也就是表中的字段。 = 312是二級索引,其中 str1 是前綴索引字段,前綴長度為 255 * 3(utf8 一個字符最多占用的字節數) = 765, =0表示 str1 是用戶定義的二級索引字段; =1的記錄是 MySQL 自己增加到二級索引中的主鍵字段。

    表中的表示編號,從 1 開始; 中的POS表示序號,從 0 開始。

    除了在 Debug 版本的 MySQL 中設置跳過數據字典表的權限檢查之外,還可以通過數據庫中的表或視圖查看其對應的數據字典表:

    數據字典表

    表或視圖

    刪除mysql表中的數據_mysql刪除多張表數據delete_mysql刪除重復數據

    ……

    ……

    3、數據字典表元數據在哪里?

    數據字典表用于存儲用戶表的元數據,這個比較好理解,因為創建用戶表的時候,所有數據字典表都已經存在了,把用戶表的各種元數據插入到相應的數據字典表就可以了。

    數據字典表本身的元數據也會保存到數據字典表里刪除mysql表中的數據,但是某個數據字典表創建的時候,有一些數據字典表還沒有創建,這就有問題了。

    我們以、這 2 個數據字典表為例來說明: 表先于 表創建, 表創建成功之后,需要把索引元數據保存到 表中,而此時 表還沒有創建, 表的索引元數據自然也就沒辦法保存到 表中了。

    MySQL 解決這個問題的方案是引入一個中間層,用于臨時存放所有數據字典表的各種元數據,等到所有數據字典表都創建完成之后,再把臨時存放在中間層的所有數據字典表的元數據保存到相應的數據字典表中。

    這里所謂的中間層實際上是一個存儲適配器,源碼中對應的類名為,這是一個實現了單例模式的類。

    MySQL 在初始化數據目錄的過程中,類的實例屬性就是所有數據字典表元數據的臨時存放場所。

    4、創建數據字典表

    我們安裝 MySQL 完成之后,想讓 MySQL 運行起來,要做的第一件事就是初始化 MySQL,實際上就是初始化 MySQL 數據目錄。

    初始化過程會創建 MySQL 運行時需要的各種表空間、數據庫、表,其中就包含數據字典表。

    創建數據字典表的過程分為 3 個步驟進行:

    第 1 步,把代表每個數據字典表的對象注冊到 類的實例屬性中。

    除了數據字典表, 中還包含了mysql 庫中的其它 MySQL 系統表。

    第 2 步,循環 中的所有表,通過 得到數據字典表的 DDL,然后調用dd::()執行 DDL 語句創建數據字典表。

    dd::() 創建數據字典表的過程中,會把表的元數據臨時存放到類的實例屬性中,而不會保存到各種元數據對應的數據字典表中,這么做的原因在上一小節中介紹數據字典表的元數據在哪里時,已經介紹過了,這里不再贅述。

    dd::() 執行完一個數據字典表的 DDL 語句之后,這個數據字典表在表空間中就已經存在了, 中的所有表都處理完成之后,所有數據字典表就都存在了。

    第 3 步,循環 中的所有表,把每個表本身的元數據(數據庫 ID、表 ID、表名、注釋、字段數量等)保存到mysql.數據字典表中,然后把表的字段、索引等元數據保存到對應的數據字典表中。

    所有數據字典表的元數據都從類的實例屬性中讀取。

    經過 3 個步驟的通力協作,所有數據字典表的元數據就都保存到數據字典表中了,這個雞生蛋、蛋生雞的問題,就這樣通過引入外力()解決了。

    5、打開數據字典表

    數據字典表保存著 MySQL 運行過程中需要的一系列關鍵數據,使用頻次很高,MySQL 啟動過程中就會把數據字典表的元數據都加載到內存中,這就是打開表的過程。

    也就是說,打開數據字典表是在 MySQL 啟動過程中完成的。

    前面我們介紹過,數據字典表的元數據也是保存在數據字典表中的。

    MySQL 啟動過程中,要先打開數據字典表才能拿到數據字典表的元數據,而要拿到數據字典表的元數據,又必須先打開數據字典表。

    刪除mysql表中的數據_mysql刪除重復數據_mysql刪除多張表數據delete

    這個過程很繞,不是很好理解,我們來打個比方:數據字典表是一個房間,數據字典表的元數據是打開房間門的鑰匙。

    現在問題來了,因為 MySQL 把數據字典表的元數據保存在數據字典表中,這就相當于把打開房間門的鑰匙落在房間里了。

    要想打開房間,必須先拿到鑰匙,而要想拿到鑰匙又必須先打開房間,這樣一轉換,問題是不是更好理解點了?

    我們先來想想怎么解決房間和鑰匙問題,如果把打開房間的鑰匙落在房間里了,有哪些辦法可以解決?

    我能想到的有以下 3 種解決方案:

    MySQL 里沒有前 2 種方案,而是留了一把備用鑰匙,也就是第 3 種方案,接下來我們看看 MySQL 打開數據字典表的過程:

    第 1 步,和創建數據字典表一樣,把代表每個數據字典表的 對象注冊到類的實例屬性中。

    每個數據字典表的 對象中,都定義了這個表的表名、字段、索引、外鍵等信息。

    對象中保存的并不是 DDL 語句,卻類似于我們建表時的 DDL 語句。

    下面這個例子是源碼中表空間數據字典表mysql.ble 對象中定義的該表的信息:

    Tablespaces::Tablespaces() {  
    m_target_def.set_table_name("tablespaces");
    m_target_def.add_field(FIELD_ID, "FIELD_ID", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT");
    m_target_def.add_field(FIELD_NAME, "FIELD_NAME", "name VARCHAR(268) NOT NULL COLLATE " + String_type(Object_table_definition_impl::name_collation()->m_coll_name));
    m_target_def.add_field(FIELD_OPTIONS, "FIELD_OPTIONS", "options MEDIUMTEXT");
    m_target_def.add_field(FIELD_SE_PRIVATE_DATA, "FIELD_SE_PRIVATE_DATA", "se_private_data MEDIUMTEXT");
    m_target_def.add_field(FIELD_COMMENT, "FIELD_COMMENT", "comment VARCHAR(2048) NOT NULL");
    m_target_def.add_field(FIELD_ENGINE, "FIELD_ENGINE", "engine VARCHAR(64) NOT NULL COLLATE utf8_general_ci");
    m_target_def.add_field(FIELD_ENGINE_ATTRIBUTE, "FIELD_ENGINE_ATTRIBUTE", "engine_attribute JSON");
    m_target_def.add_index(INDEX_PK_ID, "INDEX_PK_ID", "PRIMARY KEY(id)");
    m_target_def.add_index(INDEX_UK_NAME, "INDEX_UK_NAME", "UNIQUE KEY(name)");
    }

    第 2 步,循環 中的所有表,通過 得到數據字典表的 DDL刪除mysql表中的數據,然后調用dd::()執行 DDL 語句創建數據字典表。

    和創建數據字典表中的第 2 步不一樣,dd::() 執行 DDL,并不會真正的創建表,只是為了生成數據字典表元數據,并把元數據保存到類的實例屬性中。

    保存到 中的數據字典表元數據,就是我們前面說的備用鑰匙,有了這把備用鑰匙,就能打開數據字典表了。

    第 3 步,循環 中的所有表,通過第 2 步生成的數據字典表元數據,去 mysql 表空間中(表空間文件:mysql.ibd)讀取各個數據字典表的元數據。

    這一步執行完成之后,所有數據字典表的元數據都被加載到內存中了,數據字典表都被打開了。

    第 4 步,循環 中的所有表,把數據字典表的元數據從 刪除。

    第 5 步,循環 中所有的表,把從表空間中讀取出來的數據字典表的元數據存入 中。

    不過,這一步存入 的并不是所有數據字典表的元數據,而是 22 個核心(CORE)數據字典表的元數據:

    catalogs
    character_sets
    check_constraints
    collations
    column_statistics
    column_type_elements
    columns
    foreign_key_column_usage
    foreign_keys
    index_column_usage
    index_partitions
    indexes
    resource_groups
    schemata
    table_partition_values
    table_partitions
    tables
    tablespace_files
    tablespaces
    triggers
    view_routine_usage
    view_table_usage

    1 ~ 5 步執行完成之后, 中就只包含上面 22 個核心數據字典表的元數據了,有了這些表的元數據,就可以打開其它所有表了。

    第 6 步,調用dd::()執行FLUSH 關閉已經打開的所有數據字典表、非數據字典表,后續就可以用從數據字典表中讀取出來的元數據來打開數據字典表和其它所有需要的表了。

    到這里,打開數據字典表的大體流程就已經介紹完了,也許大家會有疑問:

    第 2 步調用dd::()執行 DDL,已經拿到了數據字典表的元數據。

    為了區分,把這里拿到的元數據叫作備用元數據。

    第 3 步根據備用元數據打開數據字典表,從表空間中讀取到數據字典表的元數據。

    同樣為了區分,把這里拿到的元數據叫作原配元數據。

    第 4 步從中刪除備用元數據。第 5 步把原配元數據存入。

    數據字典表的備用元數據和原配元數據不是一樣的嗎?為什么還要用原配元數據替換備用元數據,這是不是多此一舉?

    我沒有逐個對比備用元數據和原配元數據是否完全一樣,這是個不小的工程。不過,既然源碼中這么實現,那應該是有它的原因,只是我還沒有發現。如果后面發現其中的原因,我會再補充到我的博客中。

    6、總結

    要理解 MySQL 8.0 中的數據字典表,核心是理解以下 2 點:

    MySQL 啟動過程中,先通過 得到創建數據字典表的 DDL,調用dd::()執行 DDL,拿到元數據(備用原數據),把備用元數據臨時存放到 屬性中,再通過備用元數據打開數據字典表。

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有