上一节介绍了从命令行和配置文件加载配置参数,这一节介绍其它的初始化逻辑。可以学习的数据结构有链表和哈希,可以关注的内容有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((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 (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_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