MySQL系列(4):mysqld解析之初始化

引言

上一節介紹了從命令行和配置文件加載配置參數,這一節介紹其它的初始化邏輯。可以學習的數據結構有鏈表和哈希,可以關注的內容有table_def_size/table_cache_size/max_connections/requested_open_files等參數的計算方式,另外有需要可自行深入學習performance_schema。

源碼分析

初始化命令

init_sql_statement_names();

這裏作用是將命令存儲在sql_statement_names全局數組裏,命令種類可以參考my_sqlcommand.h,這裏定義了enum_sql_command枚舉類型,如下:

enum enum_sql_command {
  SQLCOM_SELECT,
  SQLCOM_CREATE_TABLE,
  SQLCOM_CREATE_INDEX,
  SQLCOM_ALTER_TABLE,
  SQLCOM_UPDATE,
  SQLCOM_INSERT,
  SQLCOM_INSERT_SELECT,
  SQLCOM_DELETE,
  SQLCOM_TRUNCATE,
  SQLCOM_DROP_TABLE,
  SQLCOM_DROP_INDEX,
  SQLCOM_SHOW_DATABASES,
  SQLCOM_SHOW_TABLES,
  SQLCOM_SHOW_FIELDS,
  SQLCOM_SHOW_KEYS,
  SQLCOM_SHOW_VARIABLES,
  SQLCOM_SHOW_STATUS,
  SQLCOM_SHOW_ENGINE_LOGS,
  SQLCOM_SHOW_ENGINE_STATUS,
  SQLCOM_SHOW_ENGINE_MUTEX,
  SQLCOM_SHOW_PROCESSLIST,
  SQLCOM_SHOW_MASTER_STAT,
  SQLCOM_SHOW_SLAVE_STAT,
  SQLCOM_SHOW_GRANTS,
  SQLCOM_SHOW_CREATE,
  SQLCOM_SHOW_CHARSETS,
  SQLCOM_SHOW_COLLATIONS,
  SQLCOM_SHOW_CREATE_DB,
  SQLCOM_SHOW_TABLE_STATUS,
  SQLCOM_SHOW_TRIGGERS,
  SQLCOM_LOAD,
  SQLCOM_SET_OPTION,
  SQLCOM_LOCK_TABLES,
  SQLCOM_UNLOCK_TABLES,
  SQLCOM_GRANT,
  SQLCOM_CHANGE_DB,
  SQLCOM_CREATE_DB,
  SQLCOM_DROP_DB,
  SQLCOM_ALTER_DB,
  SQLCOM_REPAIR,
  SQLCOM_REPLACE,
  SQLCOM_REPLACE_SELECT,
  SQLCOM_CREATE_FUNCTION,
  SQLCOM_DROP_FUNCTION,
  SQLCOM_REVOKE,
  SQLCOM_OPTIMIZE,
  SQLCOM_CHECK,
  SQLCOM_ASSIGN_TO_KEYCACHE,
  SQLCOM_PRELOAD_KEYS,
  SQLCOM_FLUSH,
  SQLCOM_KILL,
  SQLCOM_ANALYZE,
  SQLCOM_ROLLBACK,
  SQLCOM_ROLLBACK_TO_SAVEPOINT,
  SQLCOM_COMMIT,
  SQLCOM_SAVEPOINT,
  SQLCOM_RELEASE_SAVEPOINT,
  SQLCOM_SLAVE_START,
  SQLCOM_SLAVE_STOP,
  SQLCOM_START_GROUP_REPLICATION,
  SQLCOM_STOP_GROUP_REPLICATION,
  SQLCOM_BEGIN,
  SQLCOM_CHANGE_MASTER,
  SQLCOM_CHANGE_REPLICATION_FILTER,
  SQLCOM_RENAME_TABLE,
  SQLCOM_RESET,
  SQLCOM_PURGE,
  SQLCOM_PURGE_BEFORE,
  SQLCOM_SHOW_BINLOGS,
  SQLCOM_SHOW_OPEN_TABLES,
  SQLCOM_HA_OPEN,
  SQLCOM_HA_CLOSE,
  SQLCOM_HA_READ,
  SQLCOM_SHOW_SLAVE_HOSTS,
  SQLCOM_DELETE_MULTI,
  SQLCOM_UPDATE_MULTI,
  SQLCOM_SHOW_BINLOG_EVENTS,
  SQLCOM_DO,
  SQLCOM_SHOW_WARNS,
  SQLCOM_EMPTY_QUERY,
  SQLCOM_SHOW_ERRORS,
  SQLCOM_SHOW_STORAGE_ENGINES,
  SQLCOM_SHOW_PRIVILEGES,
  SQLCOM_HELP,
  SQLCOM_CREATE_USER,
  SQLCOM_DROP_USER,
  SQLCOM_RENAME_USER,
  SQLCOM_REVOKE_ALL,
  SQLCOM_CHECKSUM,
  SQLCOM_CREATE_PROCEDURE,
  SQLCOM_CREATE_SPFUNCTION,
  SQLCOM_CALL,
  SQLCOM_DROP_PROCEDURE,
  SQLCOM_ALTER_PROCEDURE,
  SQLCOM_ALTER_FUNCTION,
  SQLCOM_SHOW_CREATE_PROC,
  SQLCOM_SHOW_CREATE_FUNC,
  SQLCOM_SHOW_STATUS_PROC,
  SQLCOM_SHOW_STATUS_FUNC,
  SQLCOM_PREPARE,
  SQLCOM_EXECUTE,
  SQLCOM_DEALLOCATE_PREPARE,
  SQLCOM_CREATE_VIEW,
  SQLCOM_DROP_VIEW,
  SQLCOM_CREATE_TRIGGER,
  SQLCOM_DROP_TRIGGER,
  SQLCOM_XA_START,
  SQLCOM_XA_END,
  SQLCOM_XA_PREPARE,
  SQLCOM_XA_COMMIT,
  SQLCOM_XA_ROLLBACK,
  SQLCOM_XA_RECOVER,
  SQLCOM_SHOW_PROC_CODE,
  SQLCOM_SHOW_FUNC_CODE,
  SQLCOM_ALTER_TABLESPACE,
  SQLCOM_INSTALL_PLUGIN,
  SQLCOM_UNINSTALL_PLUGIN,
  SQLCOM_BINLOG_BASE64_EVENT,
  SQLCOM_SHOW_PLUGINS,
  SQLCOM_CREATE_SERVER,
  SQLCOM_DROP_SERVER,
  SQLCOM_ALTER_SERVER,
  SQLCOM_CREATE_EVENT,
  SQLCOM_ALTER_EVENT,
  SQLCOM_DROP_EVENT,
  SQLCOM_SHOW_CREATE_EVENT,
  SQLCOM_SHOW_EVENTS,
  SQLCOM_SHOW_CREATE_TRIGGER,
  SQLCOM_ALTER_DB_UPGRADE,
  SQLCOM_SHOW_PROFILE,
  SQLCOM_SHOW_PROFILES,
  SQLCOM_SIGNAL,
  SQLCOM_RESIGNAL,
  SQLCOM_SHOW_RELAYLOG_EVENTS,
  SQLCOM_GET_DIAGNOSTICS,
  SQLCOM_ALTER_USER,
  SQLCOM_EXPLAIN_OTHER,
  SQLCOM_SHOW_CREATE_USER,
  SQLCOM_SHUTDOWN,
  SQLCOM_ALTER_INSTANCE,
  SQLCOM_END
};

存到數組裏SQLCOM_SELECT對應"select",SQLCOM_SIGNAL對應"signal",這個映射是在com_status_vars數組中取的,其它同理。只有最後一個SQLCOM_END例外,對應的是"error"。sql_statement_names數組元素的類型如下:

struct st_mysql_const_lex_string
{
  const char *str;
  size_t length;
};

所以除了存儲命令名稱,還記錄了命令名稱的長度。

初始化系統變量

if (my_hash_init(&system_variable_hash, system_charset_info, 100, 0,
                   0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE,
                   PSI_INSTRUMENT_ME))
    goto error;

初始化哈希表system_variable_hash,結構如下:

typedef struct st_hash {
  size_t key_offset,key_length;
  size_t blength;
  ulong records;
  uint flags;
  DYNAMIC_ARRAY array;
  my_hash_get_key get_key;
  void (*free)(void *);
  CHARSET_INFO *charset;
  my_hash_function hash_function;
  PSI_memory_key m_psi_key;
} HASH;

size_t其實是long unsigned int類型,ulong是unsigned long int類型,uint是unsigned int uint類型,PSI_memory_key也是unsigned int類型,get_key是hash函數,free是析構函數,CHARSET_INFO *charset用來存儲字符集,
DYNAMIC_ARRAY array是動態數組,結構如下:

typedef struct st_dynamic_array
{
  uchar *buffer;
  uint elements,max_element;
  uint alloc_increment;
  uint size_of_element;
  PSI_memory_key m_psi_key;
} DYNAMIC_ARRAY;

接下來把all_sys_vars的內容插入哈希表。

if (mysql_add_sys_var_chain(all_sys_vars.first))
    goto error;

其中all_sys_vars爲sys_var類型構成的鏈表,頭尾節點初始化爲NULL,如下:

sys_var_chain all_sys_vars = { NULL, NULL };

sys_vars.h中聲明瞭sys_var的子類,有Sys_var_integer/Sys_var_typelib/Sys_var_multi_enum/Sys_var_charptr/Sys_var_proxy_user/Sys_var_dbug/Sys_var_double/Sys_var_plugin/Sys_var_debug_sync/Sys_var_have/Sys_var_struct/Sys_var_tz/Sys_var_gtid_next/Sys_var_gtid_set/Sys_var_charptr_func/Sys_var_gtid_purged等等。它們的構造函數中生成了all_sys_vars鏈表中的數據。如下:

Sys_var_integer(const char *name_arg,
          const char *comment, int flag_args, ptrdiff_t off, size_t size,
          CMD_LINE getopt,
          T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0,
          enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
          on_check_function on_check_func=0,
          on_update_function on_update_func=0,
          const char *substitute=0,
          int parse_flag= PARSE_NORMAL)
    : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
              getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
              on_check_func, on_update_func,
              substitute, parse_flag)

而系統變量對象來自於sys_vars.cc,截取其中一個,如下:

static Sys_var_mybool Sys_pfs_enabled(
       "performance_schema",
       "Enable the performance schema.",
       READ_ONLY GLOBAL_VAR(pfs_param.m_enabled),
       CMD_LINE(OPT_ARG), DEFAULT(TRUE),
       PFS_TRAILING_PROPERTIES);

調整參數

adjust_open_files_limit(requested_open_files);
adjust_max_connections(*requested_open_files);
adjust_table_cache_size(*requested_open_files);
adjust_table_def_size();

在adjust_open_files_limit裏,request_open_files由以下3種算式取最大值。而requested_open_files則是取effective_open_files和request_open_files的最小值。effective_open_files默認算出來爲65536,request_open_files默認算出來爲5000。open_files_limit控制着mysqld進程能使用的最大文件描述符數量,使用的是effective_open_files的值。

limit_1= 10 + max_connections + table_cache_size * 2;
limit_2= max_connections * 5;
limit_3= open_files_limit ? open_files_limit : 5000;

接下來adjust_max_connections裏設置max_connections,即最大連接數,取limit和原值的最小值,limit算法如下:

limit= requested_open_files - 10 - TABLE_OPEN_CACHE_MIN * 2;

其中TABLE_OPEN_CACHE_MIN爲400,所以limit默認爲4190,而通常設置的max_connections更小,所以保持不變。

limit= max<ulong>((requested_open_files - 10 - max_connections) / 2, TABLE_OPEN_CACHE_MIN);

adjust_table_cache_size裏設置table_cache_size和table_cache_size_per_instance。table_cache_size規定了內存中可打開表的數量,和max_connections類似,取limit和自身的最小值。table_cache_size_per_instance則是table_cache_size除以實例數得來的。

void adjust_table_def_size()
{
  ulong default_value;
  sys_var *var;

  default_value= min<ulong> (400 + table_cache_size / 2, 2000);
  var= intern_find_sys_var(STRING_WITH_LEN("table_definition_cache"));
  DBUG_ASSERT(var != NULL);
  var->update_default(default_value);

  if (! table_definition_cache_specified)
    table_def_size= default_value;
}

table_def_size是內存中可打開表結構的數量。這裏從前面介紹的system_variable_hash哈希表裏查找table_definition_cache系統變量,並將default_value更新到option.def_value裏。

初始化pfs

pfs_param.m_hints.m_table_definition_cache= table_def_size;
pfs_param.m_hints.m_table_open_cache= table_cache_size;
pfs_param.m_hints.m_max_connections= max_connections;
pfs_param.m_hints.m_open_files_limit= requested_open_files;
pfs_param.m_hints.m_max_prepared_stmt_count= max_prepared_stmt_count;

PSI_hook= initialize_performance_schema(&pfs_param);

pfs即performance_schema,用於記錄運行過程中的性能、資源、wait事件等信息。前面設置的table_def_size/table_cache_size/max_connections/requested_open_files等參數,也被設置到performance_schema。

關鍵詞

初始化命令;初始化系統變量;調整參數;初始化pfs


歡迎關注公衆號,獲取推送更方便,遇到問題來交流!

技術長跑

發佈了29 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章