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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql open table_MySQL open table

發布時間:2025/3/12 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql open table_MySQL open table 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景:

MySQL經常會遇到Too many open files,MySQL上的open_files_limit和OS層面上設置的open file limit有什么關系?

源碼中也會看到不同的數據結構,TABLE, TABLE_SHARE,跟表是什么關系?

MySQL flush tables又做了些什么,這幾個東西放在一起,就會比較迷惑,下面進行梳理一下:

1 數據結構

table:   MySQL為每一個查詢sql中的表建一個TABLE對象

table_share: ?MySQL為每一張表建立一個table_share對象,與frm文件對應

handler:  對應于每個TABLE對象,innodb引擎創建一個handler

dict_table_t: ?innodb為每一個ibd表load一個數據字典對象

簡略圖如下:

1. open table的過程

測試sql:select * from xpchild.pp

函數調用棧:

open_and_lock_tables

open_tables

open_and_process_table

open_table:打開一個table,并賦值給table_list->table

下面進入核心的邏輯:

開始鎖lock_open:

1.1 table_share:

首先根據db&&table_name創建一個table_share.

函數調用棧:

get_table_share_with_discover: 創建或者查找table_share對象。

get_table_share:如果全局cache:table_def_cache中存在,就直接使用,如果不存在,就創建一個table_share

alloc_table_share: 如果不存在,先分配一個share的對象。

open_table_def: 打開frm文件。

mysql_file_open: my_open打開

inline_mysql_file_close: my_close關閉

share->ref_count++;

要點:

MySQL server層維護了一個全局的table definition cache即table_def_cache,所以一個table_share只會創建一次,后續進行共享。

初始化table_share的過程中,調用文件系統打開frm文件,初始化完成后,關閉frm文件。

share結構中ref_count來表示有多少個table關聯

1.2 打開table:

open_table_from_share

step1: 初始化table中的變量,包括file handler (get_new_handler(share->db_type()))

step2: 添加各種索引,字段結構

step3: file->ha_open:ha_innobase::open 為innodb的table創建一個handler。

要點:

1. 在open table的過程中,innodb會創建一個handler,并打開ibd文件,初始化dict_table結構。

釋放鎖lock_open

1.3 close table:

sql執行結束之前,會調用close table

close_open_tables(thd)

table_def_unuse_table:

要點:

1.table_share維護了兩個雙向鏈表used_tables,free_tables,當close table的時候,

1.1 table->in_use=NULL,

1.2 把table從used_tables移除

1.3 加入到free_tables

2.全局參數table_cache_size,已經當前table_cache_count計數控制cache的置換策略

2. 再次執行sql

因為第一步已經完成了table_share的創建,并且cache了table,再次執行sql時,open table的過程就比較簡單:

2.1: get_table_share:從cache中直接獲取table_share對象

2.2:open_table_from_share:從s->free_tables中獲取緩存的可以使用的table,然后增加ref計數。

if (!share->free_tables.is_empty())

table= share->free_tables.front();

++share->ref_count;

3 系統計數:

opened_tables:系統在open_table_from_share中,對新建的table,進行thd->status_var.opened_tables++計數。

opened_shares: 系統在 open_table_def的函數中,對于首次進行open的table_share進行thd->status_var.opened_shares++計數

注: 所以當系統的status:open_tables增長比較多的時候,可以適當的增加table_cache_size,用于緩存更多的table,畢竟open table的開銷還是不小的。

4 status統計

使用show status命令,跟open有關的幾個:

{"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}

注釋:【全局變量】MySQL和innodb通過文件系統打開的文件的計數,這里包括了所有的文件,binlog,relay,alert,slow log等。

{"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC},

注釋:【全局變量】server當前打開的table_share數量,等于table_def_cache.records的數量

{"Open_tables", (char*) &show_open_tables, SHOW_FUNC}

注釋:【全局變量】 server當前打開的table數量,server維護了一個全局變量table_cache_count

{"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH}

注釋:【全局變量】 啟動以來打開過的文件的總數

{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}

注釋: 【線程變量】 在真正open_table_from_share的過程中,累計計數

{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS}

注釋: 【線程變量】 在真正打開share的時候,累計計數

注: use test的過程:

在use test的過程中,會輪詢把test db下的所有表的table_share都創建一遍,即open所有的frm文件,并創建table_share對象,最后close 所有的frm文件。

為了方便調試,寫了一個進程監控的程序:pidmon.py

在gdb的時候,可以看到mysqld進程打開的所有文件:

Too many open files:

這里包括了server層的open frm,和innodb層open ibd的時候,當打開的文件超過limit限制,就會報這個錯誤。

但這個限制牽涉到兩個參數:

一個是MySQL配置的open_files_limit

一個是OS層配置的進程的open file limit

下一篇:

flush tables究竟做了什么:close了server層創建的所有的table_share和table。

總結

以上是生活随笔為你收集整理的mysql open table_MySQL open table的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。