mysql schema详解 - xiaoboluo768/mysql-system-schema GitHub Wiki

mysql schema详解

1、MySQL 访问权限系统

1.1. MySQL 访问权限系统详解

1.1.1. MySQL 提供了哪些权限
1.1.2. MySQL 帐号命名规则
1.1.3. MySQL 帐号访问控制两阶段
1.1.3.1. 第一阶段(帐号和密码认证)
1.1.3.2. 第二阶段(权限检查)
1.1.4. 权限变更的影响
1.1.5. MySQL 常见连接问题

1.2. MySQL 访问权限系统表定义详解

MySQL 访问权限系统表包含如下几张表:

  • user:包含用户帐户和全局权限和其他非权限列表(安全配置选项和资源控制选项列)
  • db:数据库级别的权限表
  • tables_priv:表级别的权限表
  • columns_priv:列级权限表
  • procs_priv:存储过程和函数权限表
  • proxies_priv:代理用户权限表

要更改权限表的内容,推荐使用帐号管理语句(如:CREATE USER、GRANT、REVOKE)来间接修改,不建议直接使用DML语句修改权限表,否则后果自负

1.2.1. user
1.2.2. db
1.2.3. tables_priv
1.2.4. columns_priv
1.2.5. procs_priv
1.2.6. proxies_priv

2、元数据和统计信息表

2.1. 统计信息表

2.1.1. innodb_table_stats
2.1.2. innodb_index_stats

2.2. ndb_binlog_index

2.3. plugin

2.4. proc

2.5. 优化器成本模型数据

为了生成执行计划,优化器使用了基于成本的模型来对各种操作成本进行估算。优化器具有一组可编辑的默认“成本常量”(这些值存储在mysql系统数据库下的server_cost和engine_cost表中),可用于调节执行计划的决策

  • server_cost:server常规操作需要使用到的优化器成本估算常量值
  • engine_cost:针对特定存储引擎的操作需要使用到的的优化器成本估算常量值

当服务器启动时会将成本模型表读入内存中,在生成执行计划时使用内存中的值。表中指定的任何非NULL成本估算常量值优先使用。剩余其他任何NULL常量值在使用时会转换为内置的默认常量值

成本常量值在服务器运行过程中允许动态修改(通过修改server_cost和engine_cost表实现,修改完成后需要执行FLUSH OPTIMIZER_COSTS语句重新加载),如果发现修改不对或者需要重置,可以直接把响应的成本常量值设置为NULL即可

对成本常量值的修改的影响类似于全局变量的修改,只对修改之后新的连接生效,对修改之前已经建立的连接不生效(无论是否执行过FLUSH OPTIMIZER_COSTS语句)

server_cost和engine_cost表中的成本常量数据仅适用于当前实例,对其修改不会进行复制同步

参考连接:https://dev.mysql.com/doc/refman/5.7/en/cost-model.html

下面分别对这两张表进行详细说明

2.5.1. engine_cost
2.5.2. server_cost

2.6. event

2.7. func

2.8. gtid_executed

2.9. 时区系统表

MySQL服务器维护几个时区设置:

系统时区:当Server启动时,尝试确定主机的时区并使用它来设置Server的system_time_zone系统变量值。该变量为只读变量,此外,您还可以在Server启动时使用--timezone = timezone_name选项为mysqld_safe设置MySQL服务器的系统时区。或者在Server启动之前设置 TZ系统环境变量为timezone_name值

Server的当前时区。全局系统变量time_zone的值表示当前正在运行的Server时区,该系统变量的初始值为'SYSTEM',表示Server时区与系统时区相同

  • 如果系统变量time_zone设置为SYSTEM,则每个有时区计算需要的MySQL函数在调用时,都会调用系统库来确定当前的系统时区。因此,此系统调用可能会受全局互斥保护,从而导致争用发生。
  • Server的全局当前时区可以在启动时使用--default-time-zone = timezone启动选项明确指定,也可以在my.cnf中使用default-time-zone='timezone' 指定,如果您具有SUPER权限,则可以使用语句SET GLOBAL time_zone = timezone; 在Server运行时设置全局Server时区值
  • time_zone是全局,会话变量,可以在会话级别为每个会话单独设置自己的时区(连接时区),每个会话的time_zone值默认会继承time_zone系统变量的全局值,但每个会话可以使用SET time_zone = timezone;语句进行 修改。要注意:当前会话的时区设置会影响对时区敏感的时间值的显示和存储。例如:NOW()或CURTIME()等函数显示的值是使用会话时区值、TIMESTAMP数据类型列中存储和检索的值使用的是会话时区值-- TIMESTAMP列的值会从当前时区转换为UTC存储,查询时从UTC转换为当前时区。但当前时区设置不影响诸如UTC_TIMESTAMP()函数或DATE、TIME或DATETIME数据类型列中值的显示和存储--这些数据类型中的值不以UTC存储;如果有需要针对DATE、TIME或DATETIME显示时区影响,可以将它们的值转换为UTC,然后执行算术运算,然后再转换回去
  • time_zone系统变量可以设置为SYSTEM,表示与系统时区相同,也可以设置具体的时区,例如:'+10:00'或'-6:00' 表示在UTC时区的基础上,+ 10个时区或 - 6个时区(与UTC时区的偏移量),实际上相当于东十区和西六区。还可以设置为具体的时区名称,例如: 'Europe/Helsinki', 'US/Eastern', or 'MET',但是,可设置的有效值来自mysql系统字典库的time_zone表,该表中的信息需要手工使用相应的命令插入,稍后会介绍插入方法

如何填充时区表(mysql 系统字典库下有时区相关的表time_zone、time_zone_leap_second、time_zone_name、time_zone_transition、time_zone_transition_type,这些表是在MySQL初始化时创建,但不会加载数据到这些表中):

  • 如果您的系统具有自己的zoneinfo数据库(描述时区的文件集,通常在/usr/share/zoneinfo目录下),则可以使用mysql自带的mysql_tzinfo_to_sql程序来填充时区表。如果您的系统没有zoneinfo数据库,则可以使用本节后面所述的可下载软件包来进行填充时区表:
# 使用系统自带的时区数据集文件来填充MySQL 时区表(一次加载操作系统支持的所有时区),mysql_tzinfo_to_sql命令会读取您系统的时区文件并生成SQL语句来插入到MySQL的时区表中。注意:这种方式不会导入跳秒信息到time_zone_leap_second表中,需要单独操作
[root@localhost ~]# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -pletsg0
mysql: [Warning] Using a password on the command line interface can be insecure.
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.

# mysql_tzinfo_to_sql也可用于加载单个时区文件或生成闰秒信息:
## 加载单个时区文件,格式为: mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql ,如下
[root@localhost ~]# mysql_tzinfo_to_sql /usr/share/zoneinfo/Asia/Shanghai Asia/Shanghai | mysql -u root mysql -pletsg0 

## 如果您的时区需要考虑闰秒(跳秒),命令如下,其中tz_file是您的时区文件的名称(绝对路径,要注意:导入跳秒信息的时区必须要是使用了跳秒的时区,即,在time_zone表中的use_leap_second字段为Y才有跳秒信息可导入,否则该表中的信息为空):
shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql ,例如:
[root@localhost ~]# mysql_tzinfo_to_sql --leap /usr/share/zoneinfo/right/US/Arizona | mysql -u root mysql -pletsg0 

## 注意:运行mysql_tzinfo_to_sql之后,最好重新启动服务器,以便使得Server使用新的时区数据,以免它不会继续使用任何先前缓存的时区数据。

# 如果您的系统没有zoneinfo数据库(例如Windows),那么您可以使用可在MySQL Developer Zone上下载的软件包,链接如下:http://dev.mysql.com/downloads/timezones.html
## 下载完成之后导入该文件到数据库中,然后重启Server即可
shell> mysql -u root mysql <file_name

## 注意:不要使用包含MyISAM表的可下载软件包。 MySQL 5.7及更高版本使用InnoDB作为时区表。尝试用MyISAM表替换它们会导致问题。如果您的系统有zoneinfo数据库,请不要自行下载软件包。改用mysql_tzinfo_to_sql工具直接导入系统中的时区数据集。否则,您可能会在MySQL和系统上的其他应用程序之间的日期时间处理方面产生差异。

参考链接:https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html

2.9.1. time_zone
2.9.2. time_zone_leap_second
2.9.3. time_zone_name
2.9.4. time_zone_transition
2.9.5. time_zone_transition_type

2.10. servers

3、复制信息表

复制信息表用于在从库在复制主库的数据期间,用于保存从主库转发到从库的二进制日志事件、记录有关中继日志当前状态和位置的信息。一共有三种类型的日志,如下:

  • master.info文件或者mysql.slave_master_info表:用于保存从库的IO线程连接主库的连接状态、帐号、IP、端口、密码以及IO线程当前读取主库binlog的file和position等信息(被称为IO线程信息日志。默认情况下,IO线程的连接信息和状态保存在master.info文件中(默认位置在datadir下,可以使用master_info_file选项执行master.info文件路径),如果需要保存在mysql.slave_master_info表中,需要在server启动之前设置master-info-repository = TABLE)
  • relay-log.info文件或者mysql.slave_relay_log_info表:从库的IO线程从主库获取到最新的binlog事件信息会先写入到从库本地的relay log中,SQL线程再去读取relay log解析并重放,而relay_log.info文件或者mysql.slave_relay_log_info表就是用于记录最新的relay log的file和position以及SQL线程当前重放的事件对应主库binlog的file和position(relay log即被称为中继日志,SQL线程位置被称为SQL线程信息日志。默认情况下,relay log的位置信息和SQL线程的位置信息保存在relay-log.info文件中(默认位置在datadir下,可以使用relay_log_info_file选项执行relay-log.info文件路径),如果需要保存在mysql.slave_relay_log_info表中,需要在server启动之前设置relay-log-info-repository = TABLE)

设置relay_log_info_repository和master_info_repository设置为TABLE可以提高数据库本身或者所在主机意外终止之后crash recovery的能力(这两张表是innodb表,可以保证crash之后表中的位置信息不丢失),且可以保证数据一致性

从库crash时,SQL线程可能还有一部分relay log重放延迟,另外,IO线程的位置也可能正处于一个事务的中间,并不完整,所以必须在从库上启用参数relay-log-recovery=ON,启用该参数之后,从库crash recovery时会清理掉SQL线程未重放完成的relay log,并以SQL线程的位置为准重置掉IO线程的位置重新从主库请求

这两张表在数据库实例启动时如果无法被mysqld初始化,则mysqld允许继续启动,但会在错误日志中写入警告信息,这种情况在MySQL从不支持该表的版本升级到支持该表的版本时常常遇见

PS:

  • 不要尝试手动更新slave_master_info或slave_relay_log_info表,否则后果自负
  • 从库中复制线程在持续工作时,不允许任何可能对这两张表加写锁的语句执行,但允许对这两张表做只读的语句执行

3.1. slave_master_info

3.2. slave_relay_log_info

3.3. slave_worker_info

4、日志表

4.1. general_log

4.2. slow_log

5、帮助信息表

5.1. help_category

5.2. help_keyword

5.3. help_relation

5.4. help_topic

5.5. MySQL 命令行帮助

5.5.1. Server端帮助文档
5.5.2. Client 端帮助文档

6、其他

6.1. 日志审计表

6.1.1. audit_log_filter表
6.1.2. audit_log_user表

6.2. 防火墙规则表

6.2.1. firewall_users表
6.2.2. firewall_whitelist表

上一篇: information_schema详解 附录 |下一篇:MySQL 访问权限系统