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


欢迎关注公众号,获取推送更方便,遇到问题来交流!

技术长跑

猜你喜欢

转载自blog.csdn.net/CanvaChen/article/details/103744882