MariaDB 10.1.1:插件的 FLUSH 和 SHOW

INFORMATION_SCHEMA 插件类型是 MariaDB 和 MySQL 中最受欢迎的插件类型之一。INFORMATION_SCHEMA 插件会向 INFORMATION_SCHEMA 添加新表。INFORMATION_SCHEMA 插件有很多,因为它们可以用来向用户展示任何东西,而且编写起来非常容易。

MariaDB 10.1.1 带有九个 INFORMATION_SCHEMA 插件

  • Feedback — 显示匿名服务器使用信息,并可选择将其发送到配置的 URL。
  • Locales — 列出编译到服务器中的区域设置,由 Roberto Spadim 实现。
  • METADATA_LOCK_INFO — 列出服务器中的元数据锁。由 Kentoku Shiba 实现。
  • QUERY_CACHE_INFO — 列出查询缓存中的查询。最初由 Roland Bouman 实现。
  • QUERY_RESPONSE_TIME — 显示查询响应时间的分布。最初在 Percona 中实现。
  • CLIENT_STATISTICS — Percona “userstat” 补丁的一部分。
  • USER_STATISTICS — Percona “userstat” 补丁的一部分。
  • INDEX_STATISTICS — Percona “userstat” 补丁的一部分。
  • TABLE_STATISTICS — Percona “userstat” 补丁的一部分。

此外,还有许多 INFORMATION_SCHEMA 插件与存储引擎一起提供,并显示关于它们的各种信息。InnoDB 带有 28 个这样的插件。XtraDB 带有 32 个,TokuDB 带有 12 个。如果你在谷歌上搜索,你可以找到更多 INFORMATION_SCHEMA 插件——例如,一个显示各种系统信息的插件,或者一个列出所有创建的用户变量的插件。INFORMATION_SCHEMA 插件确实数量众多且非常受欢迎。

如果你查看这些插件,你会发现有些插件显示某个事物的当前状态,还有一些插件累积并显示一些统计信息。对于后一组插件,有时希望重置这些统计信息——但之前用户没有自然的方式来做到这一点。对于状态变量(如 SHOW STATUS 语句),可以使用 FLUSH STATUS,但对于插件则没有类似的功能。但现在 MariaDB 10.1.1 通过引入 reset_table 回调扩展了 INFORMATION_SCHEMA 插件 API。例如,看看 QUERY_RESPONSE_TIME 插件的初始化函数

static int query_response_time_info_init(void *p)
{
  ST_SCHEMA_TABLE *i_s_query_response_time= (ST_SCHEMA_TABLE *) p;
  i_s_query_response_time->fields_info= query_response_time_fields_info;
  i_s_query_response_time->fill_table= query_response_time_fill;
  i_s_query_response_time->reset_table= query_response_time_flush;
  query_response_time_init();
  return 0;
}

参见高亮行——它将 reset_table 回调设置为 query_response_time_flush 函数。当加载此插件时,MariaDB 将自动开始支持新语句

FLUSH QUERY_RESPONSE_TIME;

并将调用此回调,该回调将反过来重置查询响应时间统计信息。同样,“userstat” 表 CLIENT_STATISTICSUSER_STATISTICSINDEX_STATISTICSTABLE_STATISTICS 也以类似方式支持 FLUSH 语句。

MariaDB 10.1.1 还实现了 INFORMATION_SCHEMA 插件的另一个增强功能——SHOW 语句。事实上,直到 10.1.1,只有原生服务器的 INFORMATION_SCHEMA 表可以有对应的 SHOW。要查询插件的 INFORMATION_SCHEMA 表,需要输入冗长的 SELECT,然后看到长行在终端窗口中如何换行,使得无法看清每个值属于哪个列。你们都很清楚这种情况

MariaDB [test]> select * from information_schema.locales;
+-----+-------+-------------------------------------+-----------------------+-
--------------------+---------------+--------------+------------------------+
| ID  | NAME  | DESCRIPTION                         | MAX_MONTH_NAME_LENGTH | 
MAX_DAY_NAME_LENGTH | DECIMAL_POINT | THOUSAND_SEP | ERROR_MESSAGE_LANGUAGE |
+-----+-------+-------------------------------------+-----------------------+-
--------------------+---------------+--------------+------------------------+
|   0 | en_US | English - United States             |                     9 | 
9 | .             | ,            | english                |
|   1 | en_GB | English - United Kingdom            |                     9 | 
9 | .             | ,            | english                |
|   2 | ja_JP | Japanese - Japan                    |                     3 | 
3 | .             | ,            | japanese               |
|   3 | sv_SE | Swedish - Sweden                    |                     9 | 
7 | ,             |              | swedish                |
|   4 | de_DE | German - Germany                    |                     9 | 
10 | ,             | .            | german                 |
...

因此,我们为 INFORMATION_SCHEMA 插件引入了 SHOW 语句,它输入起来很快,并且应该只提供足够的列,以便在屏幕上良好地显示

MariaDB [test]> show locales;
+-----+-------+-------------------------------------+------------------------+
| Id  | Name  | Description                         | Error_Message_Language |
+-----+-------+-------------------------------------+------------------------+
|   0 | en_US | English - United States             | english                |
|   1 | en_GB | English - United Kingdom            | english                |
|   2 | ja_JP | Japanese - Japan                    | japanese               |
|   3 | sv_SE | Swedish - Sweden                    | swedish                |
|   4 | de_DE | German - Germany                    | german                 |
...

该 API 非常简单,插件无需实现任何特殊功能即可支持此功能。它只需决定在 SHOW 语句中可见哪些列子集,并在声明 INFORMATION_SCHEMA 表字段时为这些列指定名称。例如,在 LOCALES 插件中

static ST_FIELD_INFO locale_info_locale_fields_info[]=
{
  {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", 0},
  {"NAME", 255, MYSQL_TYPE_STRING, 0, 0, "Name", 0},
  {"DESCRIPTION", 255,  MYSQL_TYPE_STRING, 0, 0, "Description", 0},
  {"MAX_MONTH_NAME_LENGTH", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, 0},
  {"MAX_DAY_NAME_LENGTH", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, 0},
  {"DECIMAL_POINT", 2, MYSQL_TYPE_STRING, 0, 0, 0, 0},
  {"THOUSAND_SEP", 2, MYSQL_TYPE_STRING, 0, 0, 0, 0},
  {"ERROR_MESSAGE_LANGUAGE", 64, MYSQL_TYPE_STRING, 0, 0, "Error_Message_Language", 0},
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
};

看,高亮行指定了 SHOW 语句的列名,并且只有这些列在 SHOW 中可见。当然,插件编写者有责任选择合理的列子集,以便生成的表不会太宽,但仍然包含足够有用的信息。如果插件未为 SHOW 指定任何列名,则 SHOW 语句将不对该插件起作用。


细心的读者可能会注意到,“userstat” 表 CLIENT_STATISTICSUSER_STATISTICSINDEX_STATISTICSTABLE_STATISTICS 在 10.0 及更早的 MariaDB 版本中也支持 FLUSHSHOW。这是对的,但在 10.1.1 之前,这些表不是插件,并且语法支持是硬编码到服务器中的。现在它们是插件,这确实需要 INFORMATION_SCHEMA 插件支持 FLUSHSHOW。这就是实现这些扩展的原因。