MySQL8-中文参考-三十三-
MySQL8 中文参考(三十三)
17.15.4 InnoDB INFORMATION_SCHEMA FULLTEXT 索引表
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-fulltext_index-tables.html
以下表格提供了 FULLTEXT
索引的元数据:
mysql> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_FT%';
+-------------------------------------------+
| Tables_in_INFORMATION_SCHEMA (INNODB_FT%) |
+-------------------------------------------+
| INNODB_FT_CONFIG |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_DELETED |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_INDEX_TABLE |
| INNODB_FT_INDEX_CACHE |
+-------------------------------------------+
表格概述
-
INNODB_FT_CONFIG
:提供关于InnoDB
表的FULLTEXT
索引和相关处理的元数据。 -
INNODB_FT_BEING_DELETED
:提供INNODB_FT_DELETED
表的快照;仅在OPTIMIZE TABLE
维护操作期间使用。运行OPTIMIZE TABLE
时,INNODB_FT_BEING_DELETED
表会被清空,并且从INNODB_FT_DELETED
表中删除DOC_ID
值。由于INNODB_FT_BEING_DELETED
的内容通常寿命较短,因此该表对于监控或调试具有有限的实用性。有关在具有FULLTEXT
索引的表上运行OPTIMIZE TABLE
的信息,请参见 第 14.9.6 节,“调整 MySQL 全文搜索”。 -
INNODB_FT_DELETED
:存储从InnoDB
表的FULLTEXT
索引中删除的行。为了避免在InnoDB
FULLTEXT
索引的 DML 操作期间进行昂贵的索引重组,新删除的单词信息被单独存储,当进行文本搜索时会从搜索结果中过滤掉,并且仅当对InnoDB
表发出OPTIMIZE TABLE
语句时才从主搜索索引中��除。 -
INNODB_FT_DEFAULT_STOPWORD
:保存在创建InnoDB
表的FULLTEXT
索引时默认使用的 停用词 列表。有关
INNODB_FT_DEFAULT_STOPWORD
表的信息,请参阅 Section 14.9.4, “全文停用词”。 -
INNODB_FT_INDEX_TABLE
:提供有关用于处理对InnoDB
表的FULLTEXT
索引进行文本搜索的倒排索引的信息。 -
INNODB_FT_INDEX_CACHE
:提供有关FULLTEXT
索引中新插入行的标记信息。为避免在 DML 操作期间进行昂贵的索引重组,新索引单词的信息被单独存储,并仅在运行OPTIMIZE TABLE
时,服务器关闭时,或者缓存大小超过由innodb_ft_cache_size
或innodb_ft_total_cache_size
系统变量定义的限制时,才与主搜索索引合并。
注意
除了INNODB_FT_DEFAULT_STOPWORD
表外,这些表最初是空的。在查询任何这些表之前,将innodb_ft_aux_table
系统变量的值设置为包含FULLTEXT
索引的表的名称(包括数据库名称)(例如,test/articles
)。
示例 17.5 InnoDB FULLTEXT 索引 INFORMATION_SCHEMA 表
本示例使用具有FULLTEXT
索引的表来演示FULLTEXT
索引INFORMATION_SCHEMA
表中包含的数据。
-
创建一个具有
FULLTEXT
索引的表并插入一些数据:mysql> CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) ) ENGINE=InnoDB; mysql> INSERT INTO articles (title,body) VALUES ('MySQL Tutorial','DBMS stands for DataBase ...'), ('How To Use MySQL Well','After you went through a ...'), ('Optimizing MySQL','In this tutorial we show ...'), ('1001 MySQL Tricks','1\. Never run mysqld as root. 2\. ...'), ('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL Security','When configured properly, MySQL ...');
-
将
innodb_ft_aux_table
变量设置为具有FULLTEXT
索引的表的名称。如果未设置此变量,则InnoDB
FULLTEXT
INFORMATION_SCHEMA
表为空,除了INNODB_FT_DEFAULT_STOPWORD
。mysql> SET GLOBAL innodb_ft_aux_table = 'test/articles';
-
查询
INNODB_FT_INDEX_CACHE
表,显示FULLTEXT
索引中新插入行的信息。为避免在 DML 操作期间进行昂贵的索引重组,新插入行的数据仍保留在FULLTEXT
索引缓存中,直到运行OPTIMIZE TABLE
(或者直到服务器关闭或超过缓存限制)。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5; +------------+--------------+-------------+-----------+--------+----------+ | WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION | +------------+--------------+-------------+-----------+--------+----------+ | 1001 | 5 | 5 | 1 | 5 | 0 | | after | 3 | 3 | 1 | 3 | 22 | | comparison | 6 | 6 | 1 | 6 | 44 | | configured | 7 | 7 | 1 | 7 | 20 | | database | 2 | 6 | 2 | 2 | 31 | +------------+--------------+-------------+-----------+--------+----------+
-
启用
innodb_optimize_fulltext_only
系统变量,并在包含FULLTEXT
索引的表上运行OPTIMIZE TABLE
。此操作将FULLTEXT
索引缓存的内容刷新到主FULLTEXT
索引中。innodb_optimize_fulltext_only
改变了OPTIMIZE TABLE
语句在InnoDB
表上的操作方式,并且旨在在具有FULLTEXT
索引的InnoDB
表上的维护操作期间临时启用。mysql> SET GLOBAL innodb_optimize_fulltext_only=ON; mysql> OPTIMIZE TABLE articles; +---------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+----------+----------+----------+ | test.articles | optimize | status | OK | +---------------+----------+----------+----------+
-
查询
INNODB_FT_INDEX_TABLE
表,查看主FULLTEXT
索引中的数据信息,包括刚刚从FULLTEXT
索引缓存中刷新的数据信息。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 5; +------------+--------------+-------------+-----------+--------+----------+ | WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION | +------------+--------------+-------------+-----------+--------+----------+ | 1001 | 5 | 5 | 1 | 5 | 0 | | after | 3 | 3 | 1 | 3 | 22 | | comparison | 6 | 6 | 1 | 6 | 44 | | configured | 7 | 7 | 1 | 7 | 20 | | database | 2 | 6 | 2 | 2 | 31 | +------------+--------------+-------------+-----------+--------+----------+
INNODB_FT_INDEX_CACHE
表现在为空,因为OPTIMIZE TABLE
操作刷新了FULLTEXT
索引缓存。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5; Empty set (0.00 sec)
-
从
test/articles
表中删除一些记录。mysql> DELETE FROM test.articles WHERE id < 4;
-
查询
INNODB_FT_DELETED
表。该表记录从FULLTEXT
索引中删除的行。为了避免在 DML 操作期间进行昂贵的索引重组,新删除记录的信息被单独存储,当进行文本搜索时从搜索结果中过滤掉,并在运行OPTIMIZE TABLE
时从主搜索索引中删除。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +--------+ | DOC_ID | +--------+ | 2 | | 3 | | 4 | +--------+
-
运行
OPTIMIZE TABLE
来删除已删除的记录。mysql> OPTIMIZE TABLE articles; +---------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+----------+----------+----------+ | test.articles | optimize | status | OK | +---------------+----------+----------+----------+
INNODB_FT_DELETED
表现在应该为空。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; Empty set (0.00 sec)
-
查询
INNODB_FT_CONFIG
表。该表包含关于FULLTEXT
索引和相关处理的元数据:-
optimize_checkpoint_limit
: 多少秒后运行OPTIMIZE TABLE
停止。 -
synced_doc_id
: 下一个要发行的DOC_ID
。 -
stopword_table_name
: 用户定义的停用词表的database/table
名称。如果没有用户定义的停用词表,则VALUE
列为空。 -
use_stopword
: 指示是否使用停用词表,该表在创建FULLTEXT
索引时定义。
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +---------------------------+-------+ | KEY | VALUE | +---------------------------+-------+ | optimize_checkpoint_limit | 180 | | synced_doc_id | 8 | | stopword_table_name | | | use_stopword | 1 | +---------------------------+-------+
-
-
禁用
innodb_optimize_fulltext_only
,因为它只打算暂时启用:mysql> SET GLOBAL innodb_optimize_fulltext_only=OFF;
17.15.5 InnoDB INFORMATION_SCHEMA 缓冲池表
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-buffer-pool-tables.html
InnoDB
INFORMATION_SCHEMA
缓冲池表提供有关InnoDB
缓冲池内页面的缓冲池状态信息和元数据。
InnoDB
INFORMATION_SCHEMA
缓冲池表包括以下列出的表:
mysql> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_BUFFER%';
+-----------------------------------------------+
| Tables_in_INFORMATION_SCHEMA (INNODB_BUFFER%) |
+-----------------------------------------------+
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_POOL_STATS |
+-----------------------------------------------+
表概述
-
INNODB_BUFFER_PAGE
:包含InnoDB
缓冲池中每个页面的信息。 -
INNODB_BUFFER_PAGE_LRU
:包含关于InnoDB
缓冲池中页面的信息,特别是它们在 LRU 列表中的排序方式,该列表确定在缓冲池变满时要驱逐的页面。INNODB_BUFFER_PAGE_LRU
表与INNODB_BUFFER_PAGE
表具有相同的列,只是INNODB_BUFFER_PAGE_LRU
表具有一个LRU_POSITION
列,而不是一个BLOCK_ID
列。 -
INNODB_BUFFER_POOL_STATS
:提供缓冲池状态信息。SHOW ENGINE INNODB STATUS
输出提供了大部分相同的信息,或者可以使用InnoDB
缓冲池服务器状态变量获得。
警告
在生产系统上查询INNODB_BUFFER_PAGE
或INNODB_BUFFER_PAGE_LRU
表可能会影响性能。除非您意识到性能影响并确定其可接受,否则不要在生产系统上查询这些表。为避免影响生产系统的性能,请在测试实例上重现您想要调查的问题,并查询缓冲池统计信息。
示例 17.6 在 INNODB_BUFFER_PAGE 表中查询系统数据
此查询通过排除TABLE_NAME
值为NULL
或包含斜杠/
或句点.
的页面,提供包含系统数据的页面的近似计数,这表明用户定义了表。
mysql> SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);
+----------+
| COUNT(*) |
+----------+
| 1516 |
+----------+
此查询返回包含系统数据的页面的大致数量,缓冲池页面的总��,以及包含系统数据的页面的大致百分比。
mysql> SELECT
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0)
) AS system_pages,
(
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
) AS total_pages,
(
SELECT ROUND((system_pages/total_pages) * 100)
) AS system_page_percentage;
+--------------+-------------+------------------------+
| system_pages | total_pages | system_page_percentage |
+--------------+-------------+------------------------+
| 295 | 8192 | 4 |
+--------------+-------------+------------------------+
通过查询 PAGE_TYPE
值可以确定缓冲池中的系统数据类型。例如,以下查询返回包含系统数据的页面中的八个不同的 PAGE_TYPE
值:
mysql> SELECT DISTINCT PAGE_TYPE FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);
+-------------------+
| PAGE_TYPE |
+-------------------+
| SYSTEM |
| IBUF_BITMAP |
| UNKNOWN |
| FILE_SPACE_HEADER |
| INODE |
| UNDO_LOG |
| ALLOCATED |
+-------------------+
示例 17.7 在 INNODB_BUFFER_PAGE 表中查询用户数据
此查询通过计算 TABLE_NAME
值为 NOT NULL
且 NOT LIKE '%INNODB_TABLES%'
的页面数量,提供包含用户数据的页面的大致计数。
mysql> SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NOT NULL AND TABLE_NAME NOT LIKE '%INNODB_TABLES%';
+----------+
| COUNT(*) |
+----------+
| 7897 |
+----------+
此查询返回包含用户数据的页面的大致数量,缓冲池页面的总数,以及包含用户数据的页面的大致百分比。
mysql> SELECT
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)
) AS user_pages,
(
SELECT COUNT(*)
FROM information_schema.INNODB_BUFFER_PAGE
) AS total_pages,
(
SELECT ROUND((user_pages/total_pages) * 100)
) AS user_page_percentage;
+------------+-------------+----------------------+
| user_pages | total_pages | user_page_percentage |
+------------+-------------+----------------------+
| 7897 | 8192 | 96 |
+------------+-------------+----------------------+
此查询标识具有缓冲池中页面的用户定义表:
mysql> SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)
AND TABLE_NAME NOT LIKE '`mysql`.`innodb_%';
+-------------------------+
| TABLE_NAME |
+-------------------------+
| `employees`.`salaries` |
| `employees`.`employees` |
+-------------------------+
示例 17.8 在 INNODB_BUFFER_PAGE 表中查询索引数据
要了解索引页面的信息,请使用索引的名称查询 INDEX_NAME
列。例如,以下查询返回了在 employees.salaries
表上定义的 emp_no
索引的页面数量和页面的总数据大小:
mysql> SELECT INDEX_NAME, COUNT(*) AS Pages,
ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@GLOBAL.innodb_page_size, COMPRESSED_SIZE))/1024/1024)
AS 'Total Data (MB)'
FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE INDEX_NAME='emp_no' AND TABLE_NAME = '`employees`.`salaries`';
+------------+-------+-----------------+
| INDEX_NAME | Pages | Total Data (MB) |
+------------+-------+-----------------+
| emp_no | 1609 | 25 |
+------------+-------+-----------------+
此查询返回了在 employees.salaries
表上定义的所有索引的页面数量和页面的总数据大小:
mysql> SELECT INDEX_NAME, COUNT(*) AS Pages,
ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@GLOBAL.innodb_page_size, COMPRESSED_SIZE))/1024/1024)
AS 'Total Data (MB)'
FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE TABLE_NAME = '`employees`.`salaries`'
GROUP BY INDEX_NAME;
+------------+-------+-----------------+
| INDEX_NAME | Pages | Total Data (MB) |
+------------+-------+-----------------+
| emp_no | 1608 | 25 |
| PRIMARY | 6086 | 95 |
+------------+-------+-----------------+
示例 17.9 在 INNODB_BUFFER_PAGE_LRU 表中查询 LRU_POSITION 数据
INNODB_BUFFER_PAGE_LRU
表包含关于 InnoDB
缓冲池中页面的信息,特别是它们的排序方式,确定了在缓冲池变满时应该驱逐哪些页面。该页面的定义与 INNODB_BUFFER_PAGE
相同,只是该表具有一个 LRU_POSITION
列而不是一个 BLOCK_ID
列。
此查询计算了 employees.employees
表页面在 LRU 列中特定位置上所占的位置数。
mysql> SELECT COUNT(LRU_POSITION) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
WHERE TABLE_NAME='`employees`.`employees`' AND LRU_POSITION < 3072;
+---------------------+
| COUNT(LRU_POSITION) |
+---------------------+
| 548 |
+---------------------+
示例 17.10 查询 INNODB_BUFFER_POOL_STATS 表
INNODB_BUFFER_POOL_STATS
表提供类似于 SHOW ENGINE INNODB STATUS
和 InnoDB
缓冲池状态变量的信息。
mysql> SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS \G
*************************** 1\. row ***************************
POOL_ID: 0
POOL_SIZE: 8192
FREE_BUFFERS: 1
DATABASE_PAGES: 8173
OLD_DATABASE_PAGES: 3014
MODIFIED_DATABASE_PAGES: 0
PENDING_DECOMPRESS: 0
PENDING_READS: 0
PENDING_FLUSH_LRU: 0
PENDING_FLUSH_LIST: 0
PAGES_MADE_YOUNG: 15907
PAGES_NOT_MADE_YOUNG: 3803101
PAGES_MADE_YOUNG_RATE: 0
PAGES_MADE_NOT_YOUNG_RATE: 0
NUMBER_PAGES_READ: 3270
NUMBER_PAGES_CREATED: 13176
NUMBER_PAGES_WRITTEN: 15109
PAGES_READ_RATE: 0
PAGES_CREATE_RATE: 0
PAGES_WRITTEN_RATE: 0
NUMBER_PAGES_GET: 33069332
HIT_RATE: 0
YOUNG_MAKE_PER_THOUSAND_GETS: 0
NOT_YOUNG_MAKE_PER_THOUSAND_GETS: 0
NUMBER_PAGES_READ_AHEAD: 2713
NUMBER_READ_AHEAD_EVICTED: 0
READ_AHEAD_RATE: 0
READ_AHEAD_EVICTED_RATE: 0
LRU_IO_TOTAL: 0
LRU_IO_CURRENT: 0
UNCOMPRESS_TOTAL: 0
UNCOMPRESS_CURRENT: 0
为了比较起见,以下是基于相同数据集的 SHOW ENGINE INNODB STATUS
输出和 InnoDB
缓冲池状态变量输出。
要了解有关 SHOW ENGINE INNODB STATUS
输出的更多信息,请参阅 第 17.17.3 节,“InnoDB 标准监视器和锁监视器输出”。
mysql> SHOW ENGINE INNODB STATUS \G
...
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 579084
Buffer pool size 8192
Free buffers 1
Database pages 8173
Old database pages 3014
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 15907, not young 3803101
0.00 youngs/s, 0.00 non-youngs/s
Pages read 3270, created 13176, written 15109
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 8173, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
...
对于状态变量的描述,请参见第 7.1.10 节,“服务器状态变量”。
mysql> SHOW STATUS LIKE 'Innodb_buffer%';
+---------------------------------------+-------------+
| Variable_name | Value |
+---------------------------------------+-------------+
| Innodb_buffer_pool_dump_status | not started |
| Innodb_buffer_pool_load_status | not started |
| Innodb_buffer_pool_resize_status | not started |
| Innodb_buffer_pool_pages_data | 8173 |
| Innodb_buffer_pool_bytes_data | 133906432 |
| Innodb_buffer_pool_pages_dirty | 0 |
| Innodb_buffer_pool_bytes_dirty | 0 |
| Innodb_buffer_pool_pages_flushed | 15109 |
| Innodb_buffer_pool_pages_free | 1 |
| Innodb_buffer_pool_pages_misc | 18 |
| Innodb_buffer_pool_pages_total | 8192 |
| Innodb_buffer_pool_read_ahead_rnd | 0 |
| Innodb_buffer_pool_read_ahead | 2713 |
| Innodb_buffer_pool_read_ahead_evicted | 0 |
| Innodb_buffer_pool_read_requests | 33069332 |
| Innodb_buffer_pool_reads | 558 |
| Innodb_buffer_pool_wait_free | 0 |
| Innodb_buffer_pool_write_requests | 11985961 |
+---------------------------------------+-------------+
17.15.6 InnoDB INFORMATION_SCHEMA Metrics 表
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-metrics-table.html
INNODB_METRICS
表提供关于 InnoDB
性能和资源相关计数器的信息。
INNODB_METRICS
表列如下。有关列描述,请参见 Section 28.4.21, “INFORMATION_SCHEMA INNODB_METRICS 表”。
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G
*************************** 1\. row ***************************
NAME: dml_inserts
SUBSYSTEM: dml
COUNT: 46273
MAX_COUNT: 46273
MIN_COUNT: NULL
AVG_COUNT: 492.2659574468085
COUNT_RESET: 46273
MAX_COUNT_RESET: 46273
MIN_COUNT_RESET: NULL
AVG_COUNT_RESET: NULL
TIME_ENABLED: 2014-11-28 16:07:53
TIME_DISABLED: NULL
TIME_ELAPSED: 94
TIME_RESET: NULL
STATUS: enabled
TYPE: status_counter
COMMENT: Number of rows inserted
启用、禁用和重置计数器
您可以使用以下变量启用、禁用和重置计数器:
-
innodb_monitor_enable
: 启用计数器。SET GLOBAL innodb_monitor_enable = [counter-name|module_name|pattern|all];
-
innodb_monitor_disable
: 禁用计数器。SET GLOBAL innodb_monitor_disable = [counter-name|module_name|pattern|all];
-
innodb_monitor_reset
: 将计数器值重置为零。SET GLOBAL innodb_monitor_reset = [counter-name|module_name|pattern|all];
-
innodb_monitor_reset_all
: 重置所有计数器值。在使用innodb_monitor_reset_all
之前,必须禁用计数器。SET GLOBAL innodb_monitor_reset_all = [counter-name|module_name|pattern|all];
计数器和计数器模块也可以在启动时使用 MySQL 服务器配置文件启用。例如,要启用 log
模块,metadata_table_handles_opened
和 metadata_table_handles_closed
计数器,在 MySQL 服务器配置文件的 [mysqld]
部分中输入以下行。
[mysqld]
innodb_monitor_enable = log,metadata_table_handles_opened,metadata_table_handles_closed
在配置文件中启用多个计数器或模块时,请指定 innodb_monitor_enable
变量,后跟以逗号分隔的计数器和模块名称,如上所示。只能在配置文件中使用 innodb_monitor_enable
变量。innodb_monitor_disable
和 innodb_monitor_reset
变量仅在命令行上受支持。
注意
由于每个计数器都会增加运行时开销,建议在生产服务器上谨慎使用计数器来诊断特定问题或监视特定功能。建议在测试或开发服务器上更广泛地使用计数器。
计数器
可用计数器列表可能会更改。查询信息模式 INNODB_METRICS
表,以获��您的 MySQL 服务器版本中可用的计数器。
默认启用的计数器对应于 SHOW ENGINE INNODB STATUS
输出中显示的计数器。在 SHOW ENGINE INNODB STATUS
输出中显示的计数器始终在系统级别启用,但可以在 INNODB_METRICS
表中禁用。计数器状态不是持久的。除非另有配置,否则在服务器重新启动时,计数器会恢复到它们的默认启用或禁用状态。
如果您运行的程序会受到计数器的添加或移除影响,建议您查看发布说明并查询 INNODB_METRICS
表,以识别这些更改作为升级过程的一部分。
mysql> SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICS ORDER BY NAME;
+---------------------------------------------+---------------------+----------+
| name | subsystem | status |
+---------------------------------------------+---------------------+----------+
| adaptive_hash_pages_added | adaptive_hash_index | disabled |
| adaptive_hash_pages_removed | adaptive_hash_index | disabled |
| adaptive_hash_rows_added | adaptive_hash_index | disabled |
| adaptive_hash_rows_deleted_no_hash_entry | adaptive_hash_index | disabled |
| adaptive_hash_rows_removed | adaptive_hash_index | disabled |
| adaptive_hash_rows_updated | adaptive_hash_index | disabled |
| adaptive_hash_searches | adaptive_hash_index | enabled |
| adaptive_hash_searches_btree | adaptive_hash_index | enabled |
| buffer_data_reads | buffer | enabled |
| buffer_data_written | buffer | enabled |
| buffer_flush_adaptive | buffer | disabled |
| buffer_flush_adaptive_avg_pass | buffer | disabled |
| buffer_flush_adaptive_avg_time_est | buffer | disabled |
| buffer_flush_adaptive_avg_time_slot | buffer | disabled |
| buffer_flush_adaptive_avg_time_thread | buffer | disabled |
| buffer_flush_adaptive_pages | buffer | disabled |
| buffer_flush_adaptive_total_pages | buffer | disabled |
| buffer_flush_avg_page_rate | buffer | disabled |
| buffer_flush_avg_pass | buffer | disabled |
| buffer_flush_avg_time | buffer | disabled |
| buffer_flush_background | buffer | disabled |
| buffer_flush_background_pages | buffer | disabled |
| buffer_flush_background_total_pages | buffer | disabled |
| buffer_flush_batches | buffer | disabled |
| buffer_flush_batch_num_scan | buffer | disabled |
| buffer_flush_batch_pages | buffer | disabled |
| buffer_flush_batch_scanned | buffer | disabled |
| buffer_flush_batch_scanned_per_call | buffer | disabled |
| buffer_flush_batch_total_pages | buffer | disabled |
| buffer_flush_lsn_avg_rate | buffer | disabled |
| buffer_flush_neighbor | buffer | disabled |
| buffer_flush_neighbor_pages | buffer | disabled |
| buffer_flush_neighbor_total_pages | buffer | disabled |
| buffer_flush_n_to_flush_by_age | buffer | disabled |
| buffer_flush_n_to_flush_by_dirty_page | buffer | disabled |
| buffer_flush_n_to_flush_requested | buffer | disabled |
| buffer_flush_pct_for_dirty | buffer | disabled |
| buffer_flush_pct_for_lsn | buffer | disabled |
| buffer_flush_sync | buffer | disabled |
| buffer_flush_sync_pages | buffer | disabled |
| buffer_flush_sync_total_pages | buffer | disabled |
| buffer_flush_sync_waits | buffer | disabled |
| buffer_LRU_batches_evict | buffer | disabled |
| buffer_LRU_batches_flush | buffer | disabled |
| buffer_LRU_batch_evict_pages | buffer | disabled |
| buffer_LRU_batch_evict_total_pages | buffer | disabled |
| buffer_LRU_batch_flush_avg_pass | buffer | disabled |
| buffer_LRU_batch_flush_avg_time_est | buffer | disabled |
| buffer_LRU_batch_flush_avg_time_slot | buffer | disabled |
| buffer_LRU_batch_flush_avg_time_thread | buffer | disabled |
| buffer_LRU_batch_flush_pages | buffer | disabled |
| buffer_LRU_batch_flush_total_pages | buffer | disabled |
| buffer_LRU_batch_num_scan | buffer | disabled |
| buffer_LRU_batch_scanned | buffer | disabled |
| buffer_LRU_batch_scanned_per_call | buffer | disabled |
| buffer_LRU_get_free_loops | buffer | disabled |
| buffer_LRU_get_free_search | Buffer | disabled |
| buffer_LRU_get_free_waits | buffer | disabled |
| buffer_LRU_search_num_scan | buffer | disabled |
| buffer_LRU_search_scanned | buffer | disabled |
| buffer_LRU_search_scanned_per_call | buffer | disabled |
| buffer_LRU_single_flush_failure_count | Buffer | disabled |
| buffer_LRU_single_flush_num_scan | buffer | disabled |
| buffer_LRU_single_flush_scanned | buffer | disabled |
| buffer_LRU_single_flush_scanned_per_call | buffer | disabled |
| buffer_LRU_unzip_search_num_scan | buffer | disabled |
| buffer_LRU_unzip_search_scanned | buffer | disabled |
| buffer_LRU_unzip_search_scanned_per_call | buffer | disabled |
| buffer_pages_created | buffer | enabled |
| buffer_pages_read | buffer | enabled |
| buffer_pages_written | buffer | enabled |
| buffer_page_read_blob | buffer_page_io | disabled |
| buffer_page_read_fsp_hdr | buffer_page_io | disabled |
| buffer_page_read_ibuf_bitmap | buffer_page_io | disabled |
| buffer_page_read_ibuf_free_list | buffer_page_io | disabled |
| buffer_page_read_index_ibuf_leaf | buffer_page_io | disabled |
| buffer_page_read_index_ibuf_non_leaf | buffer_page_io | disabled |
| buffer_page_read_index_inode | buffer_page_io | disabled |
| buffer_page_read_index_leaf | buffer_page_io | disabled |
| buffer_page_read_index_non_leaf | buffer_page_io | disabled |
| buffer_page_read_other | buffer_page_io | disabled |
| buffer_page_read_rseg_array | buffer_page_io | disabled |
| buffer_page_read_system_page | buffer_page_io | disabled |
| buffer_page_read_trx_system | buffer_page_io | disabled |
| buffer_page_read_undo_log | buffer_page_io | disabled |
| buffer_page_read_xdes | buffer_page_io | disabled |
| buffer_page_read_zblob | buffer_page_io | disabled |
| buffer_page_read_zblob2 | buffer_page_io | disabled |
| buffer_page_written_blob | buffer_page_io | disabled |
| buffer_page_written_fsp_hdr | buffer_page_io | disabled |
| buffer_page_written_ibuf_bitmap | buffer_page_io | disabled |
| buffer_page_written_ibuf_free_list | buffer_page_io | disabled |
| buffer_page_written_index_ibuf_leaf | buffer_page_io | disabled |
| buffer_page_written_index_ibuf_non_leaf | buffer_page_io | disabled |
| buffer_page_written_index_inode | buffer_page_io | disabled |
| buffer_page_written_index_leaf | buffer_page_io | disabled |
| buffer_page_written_index_non_leaf | buffer_page_io | disabled |
| buffer_page_written_on_log_no_waits | buffer_page_io | disabled |
| buffer_page_written_on_log_waits | buffer_page_io | disabled |
| buffer_page_written_on_log_wait_loops | buffer_page_io | disabled |
| buffer_page_written_other | buffer_page_io | disabled |
| buffer_page_written_rseg_array | buffer_page_io | disabled |
| buffer_page_written_system_page | buffer_page_io | disabled |
| buffer_page_written_trx_system | buffer_page_io | disabled |
| buffer_page_written_undo_log | buffer_page_io | disabled |
| buffer_page_written_xdes | buffer_page_io | disabled |
| buffer_page_written_zblob | buffer_page_io | disabled |
| buffer_page_written_zblob2 | buffer_page_io | disabled |
| buffer_pool_bytes_data | buffer | enabled |
| buffer_pool_bytes_dirty | buffer | enabled |
| buffer_pool_pages_data | buffer | enabled |
| buffer_pool_pages_dirty | buffer | enabled |
| buffer_pool_pages_free | buffer | enabled |
| buffer_pool_pages_misc | buffer | enabled |
| buffer_pool_pages_total | buffer | enabled |
| buffer_pool_reads | buffer | enabled |
| buffer_pool_read_ahead | buffer | enabled |
| buffer_pool_read_ahead_evicted | buffer | enabled |
| buffer_pool_read_requests | buffer | enabled |
| buffer_pool_size | server | enabled |
| buffer_pool_wait_free | buffer | enabled |
| buffer_pool_write_requests | buffer | enabled |
| compression_pad_decrements | compression | disabled |
| compression_pad_increments | compression | disabled |
| compress_pages_compressed | compression | disabled |
| compress_pages_decompressed | compression | disabled |
| cpu_n | cpu | disabled |
| cpu_stime_abs | cpu | disabled |
| cpu_stime_pct | cpu | disabled |
| cpu_utime_abs | cpu | disabled |
| cpu_utime_pct | cpu | disabled |
| dblwr_async_requests | dblwr | disabled |
| dblwr_flush_requests | dblwr | disabled |
| dblwr_flush_wait_events | dblwr | disabled |
| dblwr_sync_requests | dblwr | disabled |
| ddl_background_drop_tables | ddl | disabled |
| ddl_log_file_alter_table | ddl | disabled |
| ddl_online_create_index | ddl | disabled |
| ddl_pending_alter_table | ddl | disabled |
| ddl_sort_file_alter_table | ddl | disabled |
| dml_deletes | dml | enabled |
| dml_inserts | dml | enabled |
| dml_reads | dml | disabled |
| dml_system_deletes | dml | enabled |
| dml_system_inserts | dml | enabled |
| dml_system_reads | dml | enabled |
| dml_system_updates | dml | enabled |
| dml_updates | dml | enabled |
| file_num_open_files | file_system | enabled |
| ibuf_merges | change_buffer | enabled |
| ibuf_merges_delete | change_buffer | enabled |
| ibuf_merges_delete_mark | change_buffer | enabled |
| ibuf_merges_discard_delete | change_buffer | enabled |
| ibuf_merges_discard_delete_mark | change_buffer | enabled |
| ibuf_merges_discard_insert | change_buffer | enabled |
| ibuf_merges_insert | change_buffer | enabled |
| ibuf_size | change_buffer | enabled |
| icp_attempts | icp | disabled |
| icp_match | icp | disabled |
| icp_no_match | icp | disabled |
| icp_out_of_range | icp | disabled |
| index_page_discards | index | disabled |
| index_page_merge_attempts | index | disabled |
| index_page_merge_successful | index | disabled |
| index_page_reorg_attempts | index | disabled |
| index_page_reorg_successful | index | disabled |
| index_page_splits | index | disabled |
| innodb_activity_count | server | enabled |
| innodb_background_drop_table_usec | server | disabled |
| innodb_dblwr_pages_written | server | enabled |
| innodb_dblwr_writes | server | enabled |
| innodb_dict_lru_count | server | disabled |
| innodb_dict_lru_usec | server | disabled |
| innodb_ibuf_merge_usec | server | disabled |
| innodb_master_active_loops | server | disabled |
| innodb_master_idle_loops | server | disabled |
| innodb_master_purge_usec | server | disabled |
| innodb_master_thread_sleeps | server | disabled |
| innodb_mem_validate_usec | server | disabled |
| innodb_page_size | server | enabled |
| innodb_rwlock_sx_os_waits | server | enabled |
| innodb_rwlock_sx_spin_rounds | server | enabled |
| innodb_rwlock_sx_spin_waits | server | enabled |
| innodb_rwlock_s_os_waits | server | enabled |
| innodb_rwlock_s_spin_rounds | server | enabled |
| innodb_rwlock_s_spin_waits | server | enabled |
| innodb_rwlock_x_os_waits | server | enabled |
| innodb_rwlock_x_spin_rounds | server | enabled |
| innodb_rwlock_x_spin_waits | server | enabled |
| lock_deadlocks | lock | enabled |
| lock_deadlock_false_positives | lock | enabled |
| lock_deadlock_rounds | lock | enabled |
| lock_rec_grant_attempts | lock | enabled |
| lock_rec_locks | lock | disabled |
| lock_rec_lock_created | lock | disabled |
| lock_rec_lock_removed | lock | disabled |
| lock_rec_lock_requests | lock | disabled |
| lock_rec_lock_waits | lock | disabled |
| lock_rec_release_attempts | lock | enabled |
| lock_row_lock_current_waits | lock | enabled |
| lock_row_lock_time | lock | enabled |
| lock_row_lock_time_avg | lock | enabled |
| lock_row_lock_time_max | lock | enabled |
| lock_row_lock_waits | lock | enabled |
| lock_schedule_refreshes | lock | enabled |
| lock_table_locks | lock | disabled |
| lock_table_lock_created | lock | disabled |
| lock_table_lock_removed | lock | disabled |
| lock_table_lock_waits | lock | disabled |
| lock_threads_waiting | lock | enabled |
| lock_timeouts | lock | enabled |
| log_checkpoints | log | disabled |
| log_concurrency_margin | log | disabled |
| log_flusher_no_waits | log | disabled |
| log_flusher_waits | log | disabled |
| log_flusher_wait_loops | log | disabled |
| log_flush_avg_time | log | disabled |
| log_flush_lsn_avg_rate | log | disabled |
| log_flush_max_time | log | disabled |
| log_flush_notifier_no_waits | log | disabled |
| log_flush_notifier_waits | log | disabled |
| log_flush_notifier_wait_loops | log | disabled |
| log_flush_total_time | log | disabled |
| log_free_space | log | disabled |
| log_full_block_writes | log | disabled |
| log_lsn_archived | log | disabled |
| log_lsn_buf_dirty_pages_added | log | disabled |
| log_lsn_buf_pool_oldest_approx | log | disabled |
| log_lsn_buf_pool_oldest_lwm | log | disabled |
| log_lsn_checkpoint_age | log | disabled |
| log_lsn_current | log | disabled |
| log_lsn_last_checkpoint | log | disabled |
| log_lsn_last_flush | log | disabled |
| log_max_modified_age_async | log | disabled |
| log_max_modified_age_sync | log | disabled |
| log_next_file | log | disabled |
| log_on_buffer_space_no_waits | log | disabled |
| log_on_buffer_space_waits | log | disabled |
| log_on_buffer_space_wait_loops | log | disabled |
| log_on_file_space_no_waits | log | disabled |
| log_on_file_space_waits | log | disabled |
| log_on_file_space_wait_loops | log | disabled |
| log_on_flush_no_waits | log | disabled |
| log_on_flush_waits | log | disabled |
| log_on_flush_wait_loops | log | disabled |
| log_on_recent_closed_wait_loops | log | disabled |
| log_on_recent_written_wait_loops | log | disabled |
| log_on_write_no_waits | log | disabled |
| log_on_write_waits | log | disabled |
| log_on_write_wait_loops | log | disabled |
| log_padded | log | disabled |
| log_partial_block_writes | log | disabled |
| log_waits | log | enabled |
| log_writer_no_waits | log | disabled |
| log_writer_on_archiver_waits | log | disabled |
| log_writer_on_file_space_waits | log | disabled |
| log_writer_waits | log | disabled |
| log_writer_wait_loops | log | disabled |
| log_writes | log | enabled |
| log_write_notifier_no_waits | log | disabled |
| log_write_notifier_waits | log | disabled |
| log_write_notifier_wait_loops | log | disabled |
| log_write_requests | log | enabled |
| log_write_to_file_requests_interval | log | disabled |
| metadata_table_handles_closed | metadata | disabled |
| metadata_table_handles_opened | metadata | disabled |
| metadata_table_reference_count | metadata | disabled |
| module_cpu | cpu | disabled |
| module_dblwr | dblwr | disabled |
| module_page_track | page_track | disabled |
| os_data_fsyncs | os | enabled |
| os_data_reads | os | enabled |
| os_data_writes | os | enabled |
| os_log_bytes_written | os | enabled |
| os_log_fsyncs | os | enabled |
| os_log_pending_fsyncs | os | enabled |
| os_log_pending_writes | os | enabled |
| os_pending_reads | os | disabled |
| os_pending_writes | os | disabled |
| page_track_checkpoint_partial_flush_request | page_track | disabled |
| page_track_full_block_writes | page_track | disabled |
| page_track_partial_block_writes | page_track | disabled |
| page_track_resets | page_track | disabled |
| purge_del_mark_records | purge | disabled |
| purge_dml_delay_usec | purge | disabled |
| purge_invoked | purge | disabled |
| purge_resume_count | purge | disabled |
| purge_stop_count | purge | disabled |
| purge_truncate_history_count | purge | disabled |
| purge_truncate_history_usec | purge | disabled |
| purge_undo_log_pages | purge | disabled |
| purge_upd_exist_or_extern_records | purge | disabled |
| sampled_pages_read | sampling | disabled |
| sampled_pages_skipped | sampling | disabled |
| trx_active_transactions | transaction | disabled |
| trx_allocations | transaction | disabled |
| trx_commits_insert_update | transaction | disabled |
| trx_nl_ro_commits | transaction | disabled |
| trx_on_log_no_waits | transaction | disabled |
| trx_on_log_waits | transaction | disabled |
| trx_on_log_wait_loops | transaction | disabled |
| trx_rollbacks | transaction | disabled |
| trx_rollbacks_savepoint | transaction | disabled |
| trx_rollback_active | transaction | disabled |
| trx_ro_commits | transaction | disabled |
| trx_rseg_current_size | transaction | disabled |
| trx_rseg_history_len | transaction | enabled |
| trx_rw_commits | transaction | disabled |
| trx_undo_slots_cached | transaction | disabled |
| trx_undo_slots_used | transaction | disabled |
| undo_truncate_count | undo | disabled |
| undo_truncate_done_logging_count | undo | disabled |
| undo_truncate_start_logging_count | undo | disabled |
| undo_truncate_usec | undo | disabled |
+---------------------------------------------+---------------------+----------+
314 rows in set (0.00 sec)
计数器模块
每个计数器与特定模块相关联。模块名称可用于启用、禁用或重置特定子系统的所有计数器。例如,使用 module_dml
可以启��与 dml
子系统相关的所有计数器。
mysql> SET GLOBAL innodb_monitor_enable = module_dml;
mysql> SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICS
WHERE subsystem ='dml';
+-------------+-----------+---------+
| name | subsystem | status |
+-------------+-----------+---------+
| dml_reads | dml | enabled |
| dml_inserts | dml | enabled |
| dml_deletes | dml | enabled |
| dml_updates | dml | enabled |
+-------------+-----------+---------+
模块名称可与 innodb_monitor_enable
和相关变量一起使用。
模块名称及其对应的 SUBSYSTEM
名称如下。
-
module_adaptive_hash
(subsystem =adaptive_hash_index
) -
module_buffer
(subsystem =buffer
) -
module_buffer_page
(subsystem =buffer_page_io
) -
module_compress
(subsystem =compression
) -
module_ddl
(subsystem =ddl
) -
module_dml
(subsystem =dml
) -
module_file
(subsystem =file_system
) -
module_ibuf_system
(subsystem =change_buffer
) -
module_icp
(subsystem =icp
) -
module_index
(subsystem =index
) -
module_innodb
(subsystem =innodb
) -
module_lock
(subsystem =lock
) -
module_log
(subsystem =log
) -
module_metadata
(subsystem =metadata
) -
module_os
(subsystem =os
) -
module_purge
(subsystem =purge
) -
module_trx
(subsystem =transaction
) -
module_undo
(subsystem =undo
)
示例 17.11 使用 INNODB_METRICS 表计数器
本示例演示了启用、禁用和重置计数器,并在 INNODB_METRICS
表中查询计数器数据。
-
创建一个简单的
InnoDB
表:mysql> USE test; Database changed mysql> CREATE TABLE t1 (c1 INT) ENGINE=INNODB; Query OK, 0 rows affected (0.02 sec)
-
启用
dml_inserts
计数器。mysql> SET GLOBAL innodb_monitor_enable = dml_inserts; Query OK, 0 rows affected (0.01 sec)
在
INNODB_METRICS
表的COMMENT
列中可以找到dml_inserts
计数器的描述:mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"; +-------------+-------------------------+ | NAME | COMMENT | +-------------+-------------------------+ | dml_inserts | Number of rows inserted | +-------------+-------------------------+
-
查询
dml_inserts
计数器数据的INNODB_METRICS
表。因为没有执行 DML 操作,计数器值为零或 NULL。TIME_ENABLED
和TIME_ELAPSED
值指示计数器上次启用的时间以及自那时经过的秒数。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G *************************** 1\. row *************************** NAME: dml_inserts SUBSYSTEM: dml COUNT: 0 MAX_COUNT: 0 MIN_COUNT: NULL AVG_COUNT: 0 COUNT_RESET: 0 MAX_COUNT_RESET: 0 MIN_COUNT_RESET: NULL AVG_COUNT_RESET: NULL TIME_ENABLED: 2014-12-04 14:18:28 TIME_DISABLED: NULL TIME_ELAPSED: 28 TIME_RESET: NULL STATUS: enabled TYPE: status_counter COMMENT: Number of rows inserted
-
向表中插入三行数据。
mysql> INSERT INTO t1 values(1); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO t1 values(2); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO t1 values(3); Query OK, 1 row affected (0.00 sec)
-
再次查询
INNODB_METRICS
表以获取dml_inserts
计数器数据。现在已经增加了许多计数器值,包括COUNT
、MAX_COUNT
、AVG_COUNT
和COUNT_RESET
。请参考INNODB_METRICS
表定义,了解这些值的描述。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G *************************** 1\. row *************************** NAME: dml_inserts SUBSYSTEM: dml COUNT: 3 MAX_COUNT: 3 MIN_COUNT: NULL AVG_COUNT: 0.046153846153846156 COUNT_RESET: 3 MAX_COUNT_RESET: 3 MIN_COUNT_RESET: NULL AVG_COUNT_RESET: NULL TIME_ENABLED: 2014-12-04 14:18:28 TIME_DISABLED: NULL TIME_ELAPSED: 65 TIME_RESET: NULL STATUS: enabled TYPE: status_counter COMMENT: Number of rows inserted
-
重置
dml_inserts
计数器,并再次查询INNODB_METRICS
表以获取dml_inserts
计数器数据。先前报告的%_RESET
值,如COUNT_RESET
和MAX_RESET
,将被设置为零。像COUNT
、MAX_COUNT
和AVG_COUNT
这样的值,从启用计数器开始累积收集数据,不受重置影响。mysql> SET GLOBAL innodb_monitor_reset = dml_inserts; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G *************************** 1\. row *************************** NAME: dml_inserts SUBSYSTEM: dml COUNT: 3 MAX_COUNT: 3 MIN_COUNT: NULL AVG_COUNT: 0.03529411764705882 COUNT_RESET: 0 MAX_COUNT_RESET: 0 MIN_COUNT_RESET: NULL AVG_COUNT_RESET: 0 TIME_ENABLED: 2014-12-04 14:18:28 TIME_DISABLED: NULL TIME_ELAPSED: 85 TIME_RESET: 2014-12-04 14:19:44 STATUS: enabled TYPE: status_counter COMMENT: Number of rows inserted
-
要重置所有计数器值,必须先禁用计数器。禁用计数器会将
STATUS
值设置为disabled
。mysql> SET GLOBAL innodb_monitor_disable = dml_inserts; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G *************************** 1\. row *************************** NAME: dml_inserts SUBSYSTEM: dml COUNT: 3 MAX_COUNT: 3 MIN_COUNT: NULL AVG_COUNT: 0.030612244897959183 COUNT_RESET: 0 MAX_COUNT_RESET: 0 MIN_COUNT_RESET: NULL AVG_COUNT_RESET: 0 TIME_ENABLED: 2014-12-04 14:18:28 TIME_DISABLED: 2014-12-04 14:20:06 TIME_ELAPSED: 98 TIME_RESET: NULL STATUS: disabled TYPE: status_counter COMMENT: Number of rows inserted
注意
计数器和模块名称支持通配符匹配。例如,可以指定
dml_i%
而不是完整的dml_inserts
计数器名称。还可以使用通配符匹配一次性启用、禁用或重置多个计数器或模块。例如,指定dml_%
以启用、禁用或重置所有以dml_
开头的计数器。 -
在禁用计数器后,可以使用
innodb_monitor_reset_all
选项重置所有计数器值。所有值都设置为零或 NULL。mysql> SET GLOBAL innodb_monitor_reset_all = dml_inserts; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G *************************** 1\. row *************************** NAME: dml_inserts SUBSYSTEM: dml COUNT: 0 MAX_COUNT: NULL MIN_COUNT: NULL AVG_COUNT: NULL COUNT_RESET: 0 MAX_COUNT_RESET: NULL MIN_COUNT_RESET: NULL AVG_COUNT_RESET: NULL TIME_ENABLED: NULL TIME_DISABLED: NULL TIME_ELAPSED: NULL TIME_RESET: NULL STATUS: disabled TYPE: status_counter COMMENT: Number of rows inserted
17.15.7 InnoDB INFORMATION_SCHEMA 临时表信息表
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-temp-table-info.html
INNODB_TEMP_TABLE_INFO
提供有关活动在InnoDB
实例中的用户创建的InnoDB
临时表的信息。它不提供有关优化器使用的内部InnoDB
临时表的信息。
mysql> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_TEMP%';
+---------------------------------------------+
| Tables_in_INFORMATION_SCHEMA (INNODB_TEMP%) |
+---------------------------------------------+
| INNODB_TEMP_TABLE_INFO |
+---------------------------------------------+
有关表定义,请参见第 28.4.27 节,“INFORMATION_SCHEMA INNODB_TEMP_TABLE_INFO 表”。
示例 17.12 INNODB_TEMP_TABLE_INFO
此示例演示了INNODB_TEMP_TABLE_INFO
表的特性。
-
创建一个简单的
InnoDB
临时表:mysql> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
-
查询
INNODB_TEMP_TABLE_INFO
以查看临时表元数据。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G *************************** 1\. row *************************** TABLE_ID: 194 NAME: #sql7a79_1_0 N_COLS: 4 SPACE: 182
TABLE_ID
是临时表的唯一标识符。NAME
列显示临时表的系统生成名称,前缀为“#sql”。列数(N_COLS
)为 4,而不是 1,因为InnoDB
始终创建三个隐藏表列(DB_ROW_ID
、DB_TRX_ID
和DB_ROLL_PTR
)。 -
重启 MySQL 并查询
INNODB_TEMP_TABLE_INFO
。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
返回一个空集,因为当服务器关闭时,
INNODB_TEMP_TABLE_INFO
及其数据不会持久保存到磁盘。 -
创建一个新的临时表。
mysql> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
-
查询
INNODB_TEMP_TABLE_INFO
以查看临时表元数据。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G *************************** 1\. row *************************** TABLE_ID: 196 NAME: #sql7b0e_1_0 N_COLS: 4 SPACE: 184
SPACE
ID 可能不同,因为它在服务器启动时动态生成。
17.15.8 从 INFORMATION_SCHEMA.FILES 检索 InnoDB 表空间元数据
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-files-table.html
信息模式FILES
表提供有关所有InnoDB
表空间类型的元数据,包括 file-per-table tablespaces、general tablespaces、system tablespace、temporary table tablespaces 和 undo tablespaces(如果存在)。
本节提供了InnoDB
特定的用法示例。有关信息模式FILES
表提供的数据的更多信息,请参阅 Section 28.3.15, “INFORMATION_SCHEMA FILES 表”。
注意
INNODB_TABLESPACES
和INNODB_DATAFILES
表还提供有关InnoDB
表空间的元数据,但数据仅限于文件表、一般表和撤销表空间。
此查询从与InnoDB
表空间相关的信息模式FILES
表的字段中检索有关InnoDB
系统表空间的元数据。与InnoDB
不相关的FILES
列始终返回NULL
,并且在查询中被排除。
mysql> SELECT FILE_ID, FILE_NAME, FILE_TYPE, TABLESPACE_NAME, FREE_EXTENTS,
TOTAL_EXTENTS, EXTENT_SIZE, INITIAL_SIZE, MAXIMUM_SIZE, AUTOEXTEND_SIZE, DATA_FREE, STATUS ENGINE
FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME LIKE 'innodb_system' \G
*************************** 1\. row ***************************
FILE_ID: 0
FILE_NAME: ./ibdata1
FILE_TYPE: TABLESPACE
TABLESPACE_NAME: innodb_system
FREE_EXTENTS: 0
TOTAL_EXTENTS: 12
EXTENT_SIZE: 1048576
INITIAL_SIZE: 12582912
MAXIMUM_SIZE: NULL
AUTOEXTEND_SIZE: 67108864
DATA_FREE: 4194304
ENGINE: NORMAL
此查询检索InnoDB
文件表和一般表空间的FILE_ID
(相当于空间 ID)和FILE_NAME
(包括路径信息)。文件表和一般表空间的文件扩展名为.ibd
。
mysql> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
WHERE FILE_NAME LIKE '%.ibd%' ORDER BY FILE_ID;
+---------+---------------------------------------+
| FILE_ID | FILE_NAME |
+---------+---------------------------------------+
| 2 | ./mysql/plugin.ibd |
| 3 | ./mysql/servers.ibd |
| 4 | ./mysql/help_topic.ibd |
| 5 | ./mysql/help_category.ibd |
| 6 | ./mysql/help_relation.ibd |
| 7 | ./mysql/help_keyword.ibd |
| 8 | ./mysql/time_zone_name.ibd |
| 9 | ./mysql/time_zone.ibd |
| 10 | ./mysql/time_zone_transition.ibd |
| 11 | ./mysql/time_zone_transition_type.ibd |
| 12 | ./mysql/time_zone_leap_second.ibd |
| 13 | ./mysql/innodb_table_stats.ibd |
| 14 | ./mysql/innodb_index_stats.ibd |
| 15 | ./mysql/slave_relay_log_info.ibd |
| 16 | ./mysql/slave_master_info.ibd |
| 17 | ./mysql/slave_worker_info.ibd |
| 18 | ./mysql/gtid_executed.ibd |
| 19 | ./mysql/server_cost.ibd |
| 20 | ./mysql/engine_cost.ibd |
| 21 | ./sys/sys_config.ibd |
| 23 | ./test/t1.ibd |
| 26 | /home/user/test/test/t2.ibd |
+---------+---------------------------------------+
此查询检索InnoDB
全局临时表空间的FILE_ID
和FILE_NAME
。全局临时表空间文件名以ibtmp
为前缀。
mysql> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
WHERE FILE_NAME LIKE '%ibtmp%';
+---------+-----------+
| FILE_ID | FILE_NAME |
+---------+-----------+
| 22 | ./ibtmp1 |
+---------+-----------+
同样,InnoDB
撤销表空间文件名以undo
为前缀。以下查询返回InnoDB
撤销表空间的FILE_ID
和FILE_NAME
。
mysql> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
WHERE FILE_NAME LIKE '%undo%';
17.16 InnoDB 与 MySQL Performance Schema 的集成
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-performance-schema.html
17.16.1 使用 Performance Schema 监控 InnoDB 表的 ALTER TABLE 进度
17.16.2 使用 Performance Schema 监控 InnoDB 互斥等待
本节简要介绍了 InnoDB
与 Performance Schema 的集成。有关全面的 Performance Schema 文档,请参阅 第二十九章,MySQL Performance Schema。
您可以使用 MySQL Performance Schema 功能 对某些内部 InnoDB
操作进行分析。这种调优主要面向专家用户,他们评估优化策略以克服性能瓶颈。数据库管理员也可以使用此功能进行容量规划,以查看其典型工作负载是否遇到特定 CPU、RAM 和磁盘存储组合的性能瓶颈;如果是,可以判断是否通过增加系统某部分的容量来改善性能。
要使用此功能检查 InnoDB
性能:
-
您必须对如何使用 Performance Schema 功能 有一般了解。例如,您应该知道如何启用仪器和消费者,以及如何查询
performance_schema
表以检索数据。有关简介概述,请参阅 第 29.1 节,“Performance Schema 快速入门”。 -
您应该熟悉可用于
InnoDB
的 Performance Schema 仪器。要查看与InnoDB
相关的仪器,您可以查询setup_instruments
表,以查找包含 'innodb
' 的仪器名称。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%innodb%'; +-------------------------------------------------------+---------+-------+ | NAME | ENABLED | TIMED | +-------------------------------------------------------+---------+-------+ | wait/synch/mutex/innodb/commit_cond_mutex | NO | NO | | wait/synch/mutex/innodb/innobase_share_mutex | NO | NO | | wait/synch/mutex/innodb/autoinc_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_zip_mutex | NO | NO | | wait/synch/mutex/innodb/cache_last_read_mutex | NO | NO | | wait/synch/mutex/innodb/dict_foreign_err_mutex | NO | NO | | wait/synch/mutex/innodb/dict_sys_mutex | NO | NO | | wait/synch/mutex/innodb/recalc_pool_mutex | NO | NO | ... | wait/io/file/innodb/innodb_data_file | YES | YES | | wait/io/file/innodb/innodb_log_file | YES | YES | | wait/io/file/innodb/innodb_temp_file | YES | YES | | stage/innodb/alter table (end) | YES | YES | | stage/innodb/alter table (flush) | YES | YES | | stage/innodb/alter table (insert) | YES | YES | | stage/innodb/alter table (log apply index) | YES | YES | | stage/innodb/alter table (log apply table) | YES | YES | | stage/innodb/alter table (merge sort) | YES | YES | | stage/innodb/alter table (read PK and internal sort) | YES | YES | | stage/innodb/buffer pool load | YES | YES | | memory/innodb/buf_buf_pool | NO | NO | | memory/innodb/dict_stats_bg_recalc_pool_t | NO | NO | | memory/innodb/dict_stats_index_map_t | NO | NO | | memory/innodb/dict_stats_n_diff_on_level | NO | NO | | memory/innodb/other | NO | NO | | memory/innodb/row_log_buf | NO | NO | | memory/innodb/row_merge_sort | NO | NO | | memory/innodb/std | NO | NO | | memory/innodb/sync_debug_latches | NO | NO | | memory/innodb/trx_sys_t::rw_trx_ids | NO | NO | ... +-------------------------------------------------------+---------+-------+ 155 rows in set (0.00 sec)
有关已仪器化的
InnoDB
对象的其他信息,您可以查询 Performance Schema 实例表,这些表提供有关已仪器化对象的其他信息。与InnoDB
相关的实例表包括:-
mutex_instances
表 -
rwlock_instances
表 -
cond_instances
表 -
file_instances
表
注意
与
InnoDB
缓冲池相关的互斥锁和读写锁不包括在此范围内;相同的情况也适用于SHOW ENGINE INNODB MUTEX
命令的输出。例如,要查看执行文件 I/O 仪表化时性能模式看到的
InnoDB
文件对象的信息,您可以发出以下查询:mysql> SELECT * FROM performance_schema.file_instances WHERE EVENT_NAME LIKE '%innodb%'\G *************************** 1\. row *************************** FILE_NAME: /home/dtprice/mysql-8.0/data/ibdata1 EVENT_NAME: wait/io/file/innodb/innodb_data_file OPEN_COUNT: 3 *************************** 2\. row *************************** FILE_NAME: /home/dtprice/mysql-8.0/data/#ib_16384_0.dblwr EVENT_NAME: wait/io/file/innodb/innodb_dblwr_file OPEN_COUNT: 2 *************************** 3\. row *************************** FILE_NAME: /home/dtprice/mysql-8.0/data/#ib_16384_1.dblwr EVENT_NAME: wait/io/file/mysql-8.0/innodb_dblwr_file OPEN_COUNT: 2 ...
-
-
您应该熟悉存储
InnoDB
事件数据的performance_schema
表。与InnoDB
相关事件相关的表包括:-
等待事件 表,存储等待事件。
-
摘要 表,为随时间终止的事件提供聚合信息。摘要表包括 file I/O 摘要表,其中聚合了有关 I/O 操作的信息。
-
阶段事件 表,存储了
InnoDB
的ALTER TABLE
和缓冲池加载操作的事件数据。更多信息,请参阅 17.16.1 节,“使用性能模式监控 InnoDB 表的 ALTER TABLE 进度”,以及使用性能模式监控缓冲池加载进度。
如果您只对与
InnoDB
相关的对象感兴趣,在查询这些表时,请使用子句WHERE EVENT_NAME LIKE '%innodb%'
或WHERE NAME LIKE '%innodb%'
(根据需要)。 -
17.16.1 监视使用性能模式的 InnoDB 表的ALTER TABLE
进度
原文:
dev.mysql.com/doc/refman/8.0/en/monitor-alter-table-performance-schema.html
您可以使用性能模式监视InnoDB
表的ALTER TABLE
进度。
有七个阶段事件代表ALTER TABLE
的不同阶段。每个阶段事件报告了整体ALTER TABLE
操作的WORK_COMPLETED
和WORK_ESTIMATED
的累计值,随着其在不同阶段的进行而不断更新。WORK_ESTIMATED
是使用一个公式计算的,该公式考虑了ALTER TABLE
执行的所有工作,并且可能在ALTER TABLE
处理过程中进行修订。WORK_COMPLETED
和WORK_ESTIMATED
的值是对ALTER TABLE
执行的所有工作的抽象表示。
按顺序,ALTER TABLE
阶段事件包括:
-
stage/innodb/alter table (read PK and internal sort)
: 当ALTER TABLE
处于读取主键阶段时,此阶段处于活动状态。它从WORK_COMPLETED=0
开始,并将WORK_ESTIMATED
设置为主键中估计的页面数。当阶段完成时,将更新WORK_ESTIMATED
为主键中实际的页面数。 -
stage/innodb/alter table (merge sort)
: 此阶段针对ALTER TABLE
操作添加的每个索引重复执行。 -
stage/innodb/alter table (insert)
: 此阶段针对ALTER TABLE
操作添加的每个索引重复执行。 -
stage/innodb/alter table (log apply index)
: 此阶段包括应用在运行ALTER TABLE
时生成的 DML 日志。 -
stage/innodb/alter table (flush)
: 在此阶段开始之前,根据刷新列表的长度,更新WORK_ESTIMATED
以获得更准确的估计。 -
stage/innodb/alter table (log apply table)
: 此阶段包括应用在运行ALTER TABLE
时生成的并发 DML 日志。此阶段的持续时间取决于表更改的程度。如果表上没有运行并发 DML,则此阶段是瞬时的。 -
stage/innodb/alter table (end)
: 包括在刷新阶段之后出现的任何剩余工作,例如在ALTER TABLE
运行时对表执行的 DML 的重新应用。
注意
InnoDB
的ALTER TABLE
阶段事件目前不考虑空间索引的添加。
使用性能模式监控ALTER TABLE
的示例
以下示例演示了如何启用stage/innodb/alter table%
阶段事件工具和相关消费者表来监控ALTER TABLE
的进度。有关性能模式阶段事件工具和相关消费者的信息,请参阅第 29.12.5 节,“性能模式阶段事件表”。
-
启用
stage/innodb/alter%
工具:mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%'; Query OK, 7 rows affected (0.00 sec) Rows matched: 7 Changed: 7 Warnings: 0
-
启用包括
events_stages_current
、events_stages_history
和events_stages_history_long
的阶段事件消费者表。mysql> UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%'; Query OK, 3 rows affected (0.00 sec) Rows matched: 3 Changed: 3 Warnings: 0
-
执行一个
ALTER TABLE
操作。在此示例中,向 employees 示例数据库的 employees 表中添加一个middle_name
列。mysql> ALTER TABLE employees.employees ADD COLUMN middle_name varchar(14) AFTER first_name; Query OK, 0 rows affected (9.27 sec) Records: 0 Duplicates: 0 Warnings: 0
-
通过查询性能模式
events_stages_current
表来检查ALTER TABLE
操作的进度。显示的阶段事件取决于当前正在进行的ALTER TABLE
阶段。WORK_COMPLETED
列显示已完成的工作。WORK_ESTIMATED
列提供了剩余工作的估计。mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current; +------------------------------------------------------+----------------+----------------+ | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | +------------------------------------------------------+----------------+----------------+ | stage/innodb/alter table (read PK and internal sort) | 280 | 1245 | +------------------------------------------------------+----------------+----------------+ 1 row in set (0.01 sec)
如果
ALTER TABLE
操作已完成,则events_stages_current
表将返回一个空集。在这种情况下,您可以查询events_stages_history
表来查看已完成操作的事件数据。例如:mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_history; +------------------------------------------------------+----------------+----------------+ | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | +------------------------------------------------------+----------------+----------------+ | stage/innodb/alter table (read PK and internal sort) | 886 | 1213 | | stage/innodb/alter table (flush) | 1213 | 1213 | | stage/innodb/alter table (log apply table) | 1597 | 1597 | | stage/innodb/alter table (end) | 1597 | 1597 | | stage/innodb/alter table (log apply table) | 1981 | 1981 | +------------------------------------------------------+----------------+----------------+ 5 rows in set (0.00 sec)
如上所示,在
ALTER TABLE
处理过程中WORK_ESTIMATED
值已经修订。初始阶段完成后的估计工作量为 1213。当ALTER TABLE
处理完成时,WORK_ESTIMATED
被设置为实际值,即 1981。
17.16.2 使用性能模式监视 InnoDB 互斥锁等待
原文:
dev.mysql.com/doc/refman/8.0/en/monitor-innodb-mutex-waits-performance-schema.html
互斥锁是代码中使用的一种同步机制,用于强制只有一个线程可以同时访问共享资源。当服务器中的两个或多个线程需要访问同一资源时,这些线程会相互竞争。第一个获得互斥锁的线程会导致其他线程等待,直到锁被释放。
对于被检测的InnoDB
互斥锁,可以使用性能模式来监视互斥锁等待。在性能模式表中收集的等待事件数据可以帮助识别具有最多等待或最长总等待时间的互斥锁,例如。
以下示例演示了如何启用InnoDB
互斥锁等待工具,如何启用相关的消费者,以及如何查询等待事件数据。
-
要查看可用的
InnoDB
互斥锁等待工具,查询性能模式setup_instruments
表。所有InnoDB
互斥锁等待工具默认情况下是禁用的。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%wait/synch/mutex/innodb%'; +---------------------------------------------------------+---------+-------+ | NAME | ENABLED | TIMED | +---------------------------------------------------------+---------+-------+ | wait/synch/mutex/innodb/commit_cond_mutex | NO | NO | | wait/synch/mutex/innodb/innobase_share_mutex | NO | NO | | wait/synch/mutex/innodb/autoinc_mutex | NO | NO | | wait/synch/mutex/innodb/autoinc_persisted_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_flush_state_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_LRU_list_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_free_list_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_zip_free_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_zip_hash_mutex | NO | NO | | wait/synch/mutex/innodb/buf_pool_zip_mutex | NO | NO | | wait/synch/mutex/innodb/cache_last_read_mutex | NO | NO | | wait/synch/mutex/innodb/dict_foreign_err_mutex | NO | NO | | wait/synch/mutex/innodb/dict_persist_dirty_tables_mutex | NO | NO | | wait/synch/mutex/innodb/dict_sys_mutex | NO | NO | | wait/synch/mutex/innodb/recalc_pool_mutex | NO | NO | | wait/synch/mutex/innodb/fil_system_mutex | NO | NO | | wait/synch/mutex/innodb/flush_list_mutex | NO | NO | | wait/synch/mutex/innodb/fts_bg_threads_mutex | NO | NO | | wait/synch/mutex/innodb/fts_delete_mutex | NO | NO | | wait/synch/mutex/innodb/fts_optimize_mutex | NO | NO | | wait/synch/mutex/innodb/fts_doc_id_mutex | NO | NO | | wait/synch/mutex/innodb/log_flush_order_mutex | NO | NO | | wait/synch/mutex/innodb/hash_table_mutex | NO | NO | | wait/synch/mutex/innodb/ibuf_bitmap_mutex | NO | NO | | wait/synch/mutex/innodb/ibuf_mutex | NO | NO | | wait/synch/mutex/innodb/ibuf_pessimistic_insert_mutex | NO | NO | | wait/synch/mutex/innodb/log_sys_mutex | NO | NO | | wait/synch/mutex/innodb/log_sys_write_mutex | NO | NO | | wait/synch/mutex/innodb/mutex_list_mutex | NO | NO | | wait/synch/mutex/innodb/page_zip_stat_per_index_mutex | NO | NO | | wait/synch/mutex/innodb/purge_sys_pq_mutex | NO | NO | | wait/synch/mutex/innodb/recv_sys_mutex | NO | NO | | wait/synch/mutex/innodb/recv_writer_mutex | NO | NO | | wait/synch/mutex/innodb/redo_rseg_mutex | NO | NO | | wait/synch/mutex/innodb/noredo_rseg_mutex | NO | NO | | wait/synch/mutex/innodb/rw_lock_list_mutex | NO | NO | | wait/synch/mutex/innodb/rw_lock_mutex | NO | NO | | wait/synch/mutex/innodb/srv_dict_tmpfile_mutex | NO | NO | | wait/synch/mutex/innodb/srv_innodb_monitor_mutex | NO | NO | | wait/synch/mutex/innodb/srv_misc_tmpfile_mutex | NO | NO | | wait/synch/mutex/innodb/srv_monitor_file_mutex | NO | NO | | wait/synch/mutex/innodb/buf_dblwr_mutex | NO | NO | | wait/synch/mutex/innodb/trx_undo_mutex | NO | NO | | wait/synch/mutex/innodb/trx_pool_mutex | NO | NO | | wait/synch/mutex/innodb/trx_pool_manager_mutex | NO | NO | | wait/synch/mutex/innodb/srv_sys_mutex | NO | NO | | wait/synch/mutex/innodb/lock_mutex | NO | NO | | wait/synch/mutex/innodb/lock_wait_mutex | NO | NO | | wait/synch/mutex/innodb/trx_mutex | NO | NO | | wait/synch/mutex/innodb/srv_threads_mutex | NO | NO | | wait/synch/mutex/innodb/rtr_active_mutex | NO | NO | | wait/synch/mutex/innodb/rtr_match_mutex | NO | NO | | wait/synch/mutex/innodb/rtr_path_mutex | NO | NO | | wait/synch/mutex/innodb/rtr_ssn_mutex | NO | NO | | wait/synch/mutex/innodb/trx_sys_mutex | NO | NO | | wait/synch/mutex/innodb/zip_pad_mutex | NO | NO | | wait/synch/mutex/innodb/master_key_id_mutex | NO | NO | +---------------------------------------------------------+---------+-------+
-
一些
InnoDB
互斥锁实例是在服务器启动时创建的,只有在服务器启动时还启用了相关的工具时才会被检测。为了确保所有InnoDB
互斥锁实例都被检测和启用,将以下performance-schema-instrument
规则添加到您的 MySQL 配置文件中:performance-schema-instrument='wait/synch/mutex/innodb/%=ON'
如果您不需要所有
InnoDB
互斥锁的等待事件数据,可以通过向 MySQL 配置文件添加额外的performance-schema-instrument
规则来禁用特定工具。例如,要禁用与全文搜索相关的InnoDB
互斥锁等待事件工具,添加以下规则:performance-schema-instrument='wait/synch/mutex/innodb/fts%=OFF'
注意
前缀较长的规则(例如
wait/synch/mutex/innodb/fts%
)优先于前缀较短的规则(例如wait/synch/mutex/innodb/%
)。在将
performance-schema-instrument
规则添加到配置文件后,重新启动服务器。除了与全文搜索相关的InnoDB
互斥锁之外,所有互斥锁都已启用。要验证,请查询setup_instruments
表。对于您启用的工具,ENABLED
和TIMED
列应设置为YES
。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%wait/synch/mutex/innodb%'; +-------------------------------------------------------+---------+-------+ | NAME | ENABLED | TIMED | +-------------------------------------------------------+---------+-------+ | wait/synch/mutex/innodb/commit_cond_mutex | YES | YES | | wait/synch/mutex/innodb/innobase_share_mutex | YES | YES | | wait/synch/mutex/innodb/autoinc_mutex | YES | YES | ... | wait/synch/mutex/innodb/master_key_id_mutex | YES | YES | +-------------------------------------------------------+---------+-------+ 49 rows in set (0.00 sec)
-
通过更新
setup_consumers
表来启用等待事件消费者。等待事件消费者默认情况下是禁用的。mysql> UPDATE performance_schema.setup_consumers SET enabled = 'YES' WHERE name like 'events_waits%'; Query OK, 3 rows affected (0.00 sec) Rows matched: 3 Changed: 3 Warnings: 0
您可以通过查询
setup_consumers
表来验证等待事件消费者是否已启用。events_waits_current
、events_waits_history
和events_waits_history_long
消费者应该已启用。mysql> SELECT * FROM performance_schema.setup_consumers; +----------------------------------+---------+ | NAME | ENABLED | +----------------------------------+---------+ | events_stages_current | NO | | events_stages_history | NO | | events_stages_history_long | NO | | events_statements_current | YES | | events_statements_history | YES | | events_statements_history_long | NO | | events_transactions_current | YES | | events_transactions_history | YES | | events_transactions_history_long | NO | | events_waits_current | YES | | events_waits_history | YES | | events_waits_history_long | YES | | global_instrumentation | YES | | thread_instrumentation | YES | | statements_digest | YES | +----------------------------------+---------+ 15 rows in set (0.00 sec)
-
一旦仪器和消费者已启用,请运行您想要监视的工作负载。在本示例中,使用mysqlslap负载仿真客户端来模拟工作负载。
$> ./mysqlslap --auto-generate-sql --concurrency=100 --iterations=10 --number-of-queries=1000 --number-char-cols=6 --number-int-cols=6;
-
查询等待事件数据。在本示例中,等待事件数据是从
events_waits_summary_global_by_event_name
表中查询的,该表汇总了events_waits_current
、events_waits_history
和events_waits_history_long
表中的数据。数据按事件名称(EVENT_NAME
)进行汇总,这是产生事件的仪器的名称。汇总的数据包括:-
COUNT_STAR
总结的等待事件数量。
-
SUM_TIMER_WAIT
总结的定时等待事件的总等待时间。
-
MIN_TIMER_WAIT
总结的定时等待事件的最小等待时间。
-
AVG_TIMER_WAIT
总结的定时等待事件的平均等待时间。
-
MAX_TIMER_WAIT
总结的定时等待事件的最大等待时间。
以下查询返回仪器名称(
EVENT_NAME
)、等待事件数量(COUNT_STAR
)以及该仪器事件的总等待时间(SUM_TIMER_WAIT
)。由于默认情况下等待时间以皮秒(万亿分之一秒)计时,等待时间除以 1000000000 以显示以毫秒为单位的等待时间。数据按照总结的等待事件数量(COUNT_STAR
)降序呈现。您可以调整ORDER BY
子句以按照总等待时间对数据进行排序。mysql> SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT/1000000000 SUM_TIMER_WAIT_MS FROM performance_schema.events_waits_summary_global_by_event_name WHERE SUM_TIMER_WAIT > 0 AND EVENT_NAME LIKE 'wait/synch/mutex/innodb/%' ORDER BY COUNT_STAR DESC; +---------------------------------------------------------+------------+-------------------+ | EVENT_NAME | COUNT_STAR | SUM_TIMER_WAIT_MS | +---------------------------------------------------------+------------+-------------------+ | wait/synch/mutex/innodb/trx_mutex | 201111 | 23.4719 | | wait/synch/mutex/innodb/fil_system_mutex | 62244 | 9.6426 | | wait/synch/mutex/innodb/redo_rseg_mutex | 48238 | 3.1135 | | wait/synch/mutex/innodb/log_sys_mutex | 46113 | 2.0434 | | wait/synch/mutex/innodb/trx_sys_mutex | 35134 | 1068.1588 | | wait/synch/mutex/innodb/lock_mutex | 34872 | 1039.2589 | | wait/synch/mutex/innodb/log_sys_write_mutex | 17805 | 1526.0490 | | wait/synch/mutex/innodb/dict_sys_mutex | 14912 | 1606.7348 | | wait/synch/mutex/innodb/trx_undo_mutex | 10634 | 1.1424 | | wait/synch/mutex/innodb/rw_lock_list_mutex | 8538 | 0.1960 | | wait/synch/mutex/innodb/buf_pool_free_list_mutex | 5961 | 0.6473 | | wait/synch/mutex/innodb/trx_pool_mutex | 4885 | 8821.7496 | | wait/synch/mutex/innodb/buf_pool_LRU_list_mutex | 4364 | 0.2077 | | wait/synch/mutex/innodb/innobase_share_mutex | 3212 | 0.2650 | | wait/synch/mutex/innodb/flush_list_mutex | 3178 | 0.2349 | | wait/synch/mutex/innodb/trx_pool_manager_mutex | 2495 | 0.1310 | | wait/synch/mutex/innodb/buf_pool_flush_state_mutex | 1318 | 0.2161 | | wait/synch/mutex/innodb/log_flush_order_mutex | 1250 | 0.0893 | | wait/synch/mutex/innodb/buf_dblwr_mutex | 951 | 0.0918 | | wait/synch/mutex/innodb/recalc_pool_mutex | 670 | 0.0942 | | wait/synch/mutex/innodb/dict_persist_dirty_tables_mutex | 345 | 0.0414 | | wait/synch/mutex/innodb/lock_wait_mutex | 303 | 0.1565 | | wait/synch/mutex/innodb/autoinc_mutex | 196 | 0.0213 | | wait/synch/mutex/innodb/autoinc_persisted_mutex | 196 | 0.0175 | | wait/synch/mutex/innodb/purge_sys_pq_mutex | 117 | 0.0308 | | wait/synch/mutex/innodb/srv_sys_mutex | 94 | 0.0077 | | wait/synch/mutex/innodb/ibuf_mutex | 22 | 0.0086 | | wait/synch/mutex/innodb/recv_sys_mutex | 12 | 0.0008 | | wait/synch/mutex/innodb/srv_innodb_monitor_mutex | 4 | 0.0009 | | wait/synch/mutex/innodb/recv_writer_mutex | 1 | 0.0005 | +---------------------------------------------------------+------------+-------------------+
注意
前面的结果集包括在启动过程中产生的等待事件数据。为了排除这些数据,您可以在启动后立即截断
events_waits_summary_global_by_event_name
表,然后再运行您的工作负载。但是,��断操作本身可能会产生微不足道的等待事件数据。mysql> TRUNCATE performance_schema.events_waits_summary_global_by_event_name;
-
17.17 InnoDB 监视器
17.17.1 InnoDB Monitor Types
17.17.2 启用 InnoDB 监视器
17.17.3 InnoDB Standard Monitor and Lock Monitor Output
InnoDB
监视器提供有关 InnoDB
内部状态的信息。这些信息对性能调优很有用。
17.17.1 InnoDB 监视器类型
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-monitor-types.html
有两种类型的InnoDB
监视器:
-
标准
InnoDB
监视器显示以下类型的信息:-
主后台线程完成的工作
-
信号量等待
-
最近的外键和死锁错误数据
-
事务的锁等待
-
活动事务持有的表和记录锁
-
待处理的 I/O 操作及相关统计信息
-
插入缓冲区和自适应哈希索引统计信息
-
重做日志数据
-
缓冲池统计信息
-
行操作数据
-
-
InnoDB
锁监视器会在标准InnoDB
监视器输出中打印额外的锁信息。
17.17.2 启用 InnoDB 监视器
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-enabling-monitors.html
当为定期输出启用 InnoDB
监视器时,InnoDB
每隔约 15 秒将输出写入到 mysqld 服务器标准错误输出 (stderr
)。
InnoDB
将监视器输出发送到 stderr
而不是 stdout
或固定大小的内存缓冲区,以避免潜在的缓冲区溢出。
在 Windows 上,stderr
通常会被定向到默认日志文件,除非另有配置。如果想将输出定向到控制台窗口而不是错误日志,请在控制台窗口中的命令提示符下使用 --console
选项启动服务器。更多信息,请参见 Windows 上的默认错误日志目的地。
在 Unix 和类 Unix 系统上,stderr
通常会被定向到终端,除非另有配置。更多信息,请参见 Unix 和类 Unix 系统上的默认错误日志目的地。
只有在实际需要查看监视器信息时才应启用 InnoDB
监视器,因为输出生成会导致一定的性能降低。此外,如果监视器输出被定向到错误日志,如果忘记后续禁用监视器,日志可能会变得非常庞大。
注意
为了帮助故障排除,在某些条件下,InnoDB
会临时启用标准 InnoDB
监视器输出。更多信息,请参见 第 17.21 节,“InnoDB 故障排除”。
InnoDB
监视器输出以包含时间戳和监视器名称的标题开头。例如:
=====================================
2014-10-16 18:37:29 0x7fc2a95c1700 INNODB MONITOR OUTPUT
=====================================
标准 InnoDB
监视器的标题 (INNODB MONITOR OUTPUT
) 也用于锁监视器,因为后者会生成相同的输出并附加额外的锁信息。
innodb_status_output
和 innodb_status_output_locks
系统变量用于启用标准 InnoDB
监视器和 InnoDB
锁监视器。
需要 PROCESS
权限才能启用或禁用 InnoDB
监视器。
启用标准 InnoDB
监视器
通过将 innodb_status_output
系统变量设置为 ON
来启用标准 InnoDB
监视器。
SET GLOBAL innodb_status_output=ON;
要禁用标准 InnoDB
监视器,请将 innodb_status_output
设置为 OFF
。
当关闭服务器时,innodb_status_output
变量将设置为默认值 OFF
。
启用 InnoDB 锁监视器
InnoDB
锁监视器数据与 InnoDB
标准监视器输出一起打印。必须同时启用 InnoDB
标准监视器和 InnoDB
锁监视器,才能定期打印 InnoDB
锁监视器数据。
要启用 InnoDB
锁监视器,请将 innodb_status_output_locks
系统变量设置为 ON
。必须同时启用 InnoDB
标准监视器和 InnoDB
锁监视器,才能定期打印 InnoDB
锁监视器数据:
SET GLOBAL innodb_status_output=ON;
SET GLOBAL innodb_status_output_locks=ON;
要禁用 InnoDB
锁监视器,请将 innodb_status_output_locks
设置为 OFF
。将 innodb_status_output
设置为 OFF
也会禁用 InnoDB
标准监视器。
当关闭服务器时,innodb_status_output
和 innodb_status_output_locks
变量将设置为默认值 OFF
。
注意
要为 SHOW ENGINE INNODB STATUS
输出启用 InnoDB
锁监视器,只需启用 innodb_status_output_locks
即可。
根据需要获取标准 InnoDB 监视器输出
作为定期输出标准 InnoDB
监视器的替代方法,您可以根据需要使用 SHOW ENGINE INNODB STATUS
SQL 语句获取标准 InnoDB
监视器输出,该语句将输出提取到您的客户端程序。如果您使用 mysql 交互式客户端,则如果将通常的分号语句终止符替换为 \G
,输出将更易读:
mysql> SHOW ENGINE INNODB STATUS\G
SHOW ENGINE INNODB STATUS
输出还包括 InnoDB
锁监视器数据,如果启用了 InnoDB
锁监视器。
将标准 InnoDB 监视器输出定向到状态文件
可以通过在启动时指定 --innodb-status-file
选项来启用并将标准 InnoDB
监视器输出定向到状态文件。使用此选项时,InnoDB
在数据目录中创建一个名为 innodb_status.*
pid*
的文件,并每隔约 15 秒将输出写入其中。
当服务器正常关闭时,InnoDB
会删除状态文件。如果发生异常关闭,则可能需要手动删除状态文件。
--innodb-status-file
选项仅供临时使用,因为输出生成可能会影响性能,并且随着时间推移,innodb_status.*
pid*
文件可能会变得非常大。
17.17.3 InnoDB 标准监视器和锁监视器输出
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-standard-monitor.html
锁监视器与标准监视器相同,只是它包含额外的锁信息。启用周期性输出的任一监视器会打开相同的输出流,但如果启用了锁监视器,则该流会包含额外的信息。例如,如果你启用了标准监视器和锁监视器,那么会打开一个单一的输出流。该流会包含额外的锁信息,直到你禁用锁监视器。
使用SHOW ENGINE INNODB STATUS
语句生成的标准监视器输出在达到 1MB 时受到限制。此限制不适用于写入服务器标准错误输出(stderr
)的输出。
示例标准监视器输出:
mysql> SHOW ENGINE INNODB STATUS\G
*************************** 1\. row ***************************
Type: InnoDB
Name:
Status:
=====================================
2018-04-12 15:14:08 0x7f971c063700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 4 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 15 srv_active, 0 srv_shutdown, 1122 srv_idle
srv_master_thread log flush and writes: 0
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 24
OS WAIT ARRAY INFO: signal count 24
RW-shared spins 4, rounds 8, OS waits 4
RW-excl spins 2, rounds 60, OS waits 2
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 2.00 RW-shared, 30.00 RW-excl, 0.00 RW-sx
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2018-04-12 14:57:24 0x7f97a9c91700 Transaction:
TRANSACTION 7717, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 3
MySQL thread id 8, OS thread handle 140289365317376, query id 14 localhost root update
INSERT INTO child VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5), (NULL, 6)
Foreign key constraint fails for table `test`.`child`:
,
CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE
CASCADE ON UPDATE CASCADE
Trying to add in child table, in index par_ind tuple:
DATA TUPLE: 2 fields;
0: len 4; hex 80000003; asc ;;
1: len 4; hex 80000003; asc ;;
But in parent table `test`.`parent`, in index PRIMARY,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000004; asc ;;
1: len 6; hex 000000001e19; asc ;;
2: len 7; hex 81000001110137; asc 7;;
------------
TRANSACTIONS
------------
Trx id counter 7748
Purge done for trx's n:o < 7747 undo n:o < 0 state: running but idle
History list length 19
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421764459790000, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 7747, ACTIVE 23 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 9, OS thread handle 140286987249408, query id 51 localhost root updating
DELETE FROM t WHERE i = 1
------- TRX HAS BEEN WAITING 23 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 4 page no 4 n bits 72 index GEN_CLUST_INDEX of table `test`.`t`
trx id 7747 lock_mode X waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 6; hex 000000000202; asc ;;
1: len 6; hex 000000001e41; asc A;;
2: len 7; hex 820000008b0110; asc ;;
3: len 4; hex 80000001; asc ;;
------------------
TABLE LOCK table `test`.`t` trx id 7747 lock mode IX
RECORD LOCKS space id 4 page no 4 n bits 72 index GEN_CLUST_INDEX of table `test`.`t`
trx id 7747 lock_mode X waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 6; hex 000000000202; asc ;;
1: len 6; hex 000000001e41; asc A;;
2: len 7; hex 820000008b0110; asc ;;
3: len 4; hex 80000001; asc ;;
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
833 OS file reads, 605 OS file writes, 208 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 553253, node heap has 0 buffer(s)
Hash table size 553253, node heap has 1 buffer(s)
Hash table size 553253, node heap has 3 buffer(s)
Hash table size 553253, node heap has 0 buffer(s)
Hash table size 553253, node heap has 0 buffer(s)
Hash table size 553253, node heap has 0 buffer(s)
Hash table size 553253, node heap has 0 buffer(s)
Hash table size 553253, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 19643450
Log buffer assigned up to 19643450
Log buffer completed up to 19643450
Log written up to 19643450
Log flushed up to 19643450
Added dirty pages up to 19643450
Pages flushed up to 19643450
Last checkpoint at 19643450
129 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872
Dictionary memory allocated 409606
Buffer pool size 131072
Free buffers 130095
Database pages 973
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 810, created 163, written 404
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 973, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size 65536
Free buffers 65043
Database pages 491
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 411, created 80, written 210
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 491, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size 65536
Free buffers 65052
Database pages 482
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 399, created 83, written 194
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 482, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=5772, Main thread ID=140286437054208 , state=sleeping
Number of rows inserted 57, updated 354, deleted 4, read 4421
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
标准监视器输出部分
有关标准监视器报告的每个指标的描述,请参考 Oracle Enterprise Manager for MySQL Database User's Guide 中的指标章节。
-
状态
本部分显示时间戳、监视器名称以及每秒平均值基于的秒数。秒数是当前时间与上次打印
InnoDB
监视器输出之间的经过时间。 -
后台线程
srv_master_thread
行显示了主后台线程执行的工作。 -
信号量
本部分报告了等待信号量的线程以及线程需要自旋或在互斥量或读写锁信号量上等待的次数的统计信息。大量等待信号量的线程可能是由于磁盘 I/O 或
InnoDB
内部争用问题引起的。争用可能是由于查询的重度并行性或操作系统线程调度问题引起的。在这种情况下,将innodb_thread_concurrency
系统变量设置为小于默认值可能有所帮助。每次等待的自旋轮数
行显示了每个 OS 等待互斥量的自旋锁轮数。互斥量指标由
SHOW ENGINE INNODB MUTEX
报告。 -
最新外键错误
本部分提供了关于最近的外键约束错误的信息。如果没有发生此类错误,则不会显示。内容包括失败的语句以及有关失败约束的信息以及引用和引用表的信息。
-
最新检测到的死锁
这一部分提供了关于最近死锁的信息。如果没有发生死锁,则不会显示。内容显示了涉及的事务、每个事务试图执行的语句、它们拥有和需要的锁,以及
InnoDB
决定回滚以打破死锁的事务。本节中报告的锁模式在第 17.7.1 节,“InnoDB 锁定”中有解释。 -
事务
如果此部分报告锁等待,您的应用程序可能存在锁争用。输出还可以帮助跟踪事务死锁的原因。
-
文件 I/O
这一部分提供了关于
InnoDB
用于执行各种类型 I/O 的线程的信息。其中前几个专门用于一般的InnoDB
处理。内容还显示了待处理 I/O 操作的信息和 I/O 性能的统计信息。这些线程的数量由
innodb_read_io_threads
和innodb_write_io_threads
参数控制。请参阅第 17.14 节,“InnoDB 启动选项和系统变量”。 -
插入缓冲区和自适应哈希索引
这一部分显示了
InnoDB
插入缓冲区(也称为更改缓冲区)和自适应哈希索引的状态。有关更多信息,请参阅第 17.5.2 节,“更改缓冲区”和第 17.5.3 节,“自适应哈希索引”。
-
日志
这一部分显示了关于
InnoDB
日志的信息。内容包括当前日志序列号、日志已刷新到磁盘的位置,以及InnoDB
上次进行检查点的位置。 (参见第 17.11.3 节,“InnoDB 检查点”.) 本节还显示了有关待写入和写入性能统计的信息。 -
缓冲池和内存
这一部分为您提供了关于读取和写入页面的统计信息。您可以根据这些数字计算出您的查询当前正在执行多少数据文件 I/O 操作。
有关缓冲池统计描述,请参阅使用 InnoDB 标准监视器监视缓冲池。有关缓冲池操作的其他信息,请参阅第 17.5.1 节,“缓冲池”。
-
行操作
这一部分展示了主线程正在做的事情,包括每种类型的行操作的数量和性能率。
17.18 InnoDB 备份和恢复
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-backup-recovery.html
17.18.1 InnoDB 备份
17.18.2 InnoDB 恢复
本节涵盖与InnoDB
备份和恢复相关的主题。
-
有关适用于
InnoDB
的备份技术的信息,请参阅第 17.18.1 节,“InnoDB 备份”。 -
有关时间点恢复、从磁盘故障或损坏中恢复以及
InnoDB
如何执行崩溃恢复的信息,请参阅第 17.18.2 节,“InnoDB 恢复”。
17.18.1 InnoDB 备份
安全数据库管理的关键是定期备份。根据您的数据量、MySQL 服务器数量和数据库工作量,您可以单独或结合使用以下备份技术:使用MySQL Enterprise Backup进行热备份;在 MySQL 服务器关闭时通过复制文件进行冷备份;使用mysqldump进行逻辑备份,适用于较小的数据量或记录模式对象的结构。热备份和冷备份是物理备份,复制实际数据文件,可以直接被mysqld服务器用于更快的恢复。
使用MySQL Enterprise Backup是备份InnoDB
数据的推荐方法。
注意
InnoDB
不支持使用第三方备份工具还原的数据库。
热备份
mysqlbackup命令是 MySQL Enterprise Backup 组件的一部分,允许您备份运行中的 MySQL 实例,包括InnoDB
表,在产生一致的数据库快照的同时最小化对操作的干扰。当mysqlbackup复制InnoDB
表时,对InnoDB
表的读写可以继续。MySQL Enterprise Backup 还可以创建压缩备份文件,并备份表和数据库的子集。结合 MySQL 二进制日志,用户可以执行按时间点恢复。MySQL Enterprise Backup 是 MySQL Enterprise 订阅的一部分。有关更多详细信息,请参见 Section 32.1, “MySQL Enterprise Backup Overview”。
冷备份
如果可以关闭 MySQL 服务器,可以进行包含InnoDB
用于管理其表的所有文件的物理备份。使用以下步骤:
-
执行慢关闭 MySQL 服务器,并确保它在没有错误的情况下停止。
-
将所有
InnoDB
数据文件(ibdata
文件和.ibd
文件)复制到安全位置。 -
将所有
InnoDB
重做日志文件(MySQL 8.0.30 及更高版本中的#ib_redo*
N*
文件或早期版本中的ib_logfile
文件)复制到安全位置。 -
将您的
my.cnf
配置文件或文件复制到安全位置。
使用 mysqldump 进行逻辑备份
除了物理备份之外,建议您定期使用mysqldump转储表格,创建逻辑备份。二进制文件可能会在您没有注意到的情况下损坏。转储的表格存储在人类可读的文本文件中,因此更容易发现表格损坏。此外,由于格式更简单,严重数据损坏的机会更小。mysqldump还具有--single-transaction
选项,可以在不锁定其他客户端的情况下创建一致的快照。请参阅第 9.3.1 节,“建立备份策略”。
复制功能适用于InnoDB
表格,因此您可以使用 MySQL 复制功能在需要高可用性的数据库站点保留数据库副本。请参阅第 17.19 节,“InnoDB 和 MySQL 复制”。
17.18.2 InnoDB 恢复
本节描述了InnoDB
恢复。主题包括:
-
时间点恢复
-
从数据损坏或磁盘故障中恢复
-
InnoDB ��溃恢复
-
崩溃恢复中的表空间发现
时间点恢复
要将InnoDB
数据库从物理备份的时间恢复到当前状态,必须在进行备份之前启用 MySQL 服务器的二进制日志记录。在恢复备份后实现时间点恢复,可以应用在备份后发生的二进制日志更改。参见第 9.5 节,“时间点(增量)恢复” Recovery")。
从数据损坏或磁盘故障中恢复
如果您的数据库损坏或磁盘故障发生,您必须使用备份执行恢复。在损坏的情况下,首先找到一个没有损坏的备份。恢复基本备份后,使用mysqlbinlog和mysql从二进制日志文件中执行时间点恢复,以恢复备份后发生的更改。
在某些数据库损坏的情况下,只需转储、删除和重新创建一个或几个损坏的表即可。您可以使用CHECK TABLE
语句来检查表是否损坏,尽管CHECK TABLE
自然无法检测到每种可能的损坏。
在某些情况下,表面上的数据库页损坏实际上是由于操作系统损坏了自己的文件缓存,磁盘上的数据可能是正常的。最好先尝试重新启动计算机。这样做可能会消除看起来是数据库页损坏的错误。如果 MySQL 由于InnoDB
一致性问题而仍然无法启动,请参见第 17.21.3 节,“强制 InnoDB 恢复”,了解在恢复模式下启动实例的步骤,这样可以让您转储数据。
InnoDB 崩溃恢复
要从意外的 MySQL 服务器退出中恢复,唯一的要求是重新启动 MySQL 服务器。InnoDB
会自动检查日志并将数据库回滚到当前状态。InnoDB
会自动回滚在崩溃时存在的未提交事务。
InnoDB
崩溃恢复包括几个步骤:
-
表空间发现
表空间发现是
InnoDB
用来识别需要重做日志应用的表空间的过程。请参阅崩溃恢复期间的表空间发现。 -
重做日志应用
重做日志应用是在初始化期间执行的,在接受任何连接之前。如果在关闭或崩溃时从缓冲池中的所有更改都被刷新到表空间(
ibdata*
和*.ibd
文件),则会跳过重做日志应用。如果在启动时重做日志文件丢失,InnoDB
也会跳过重做日志应用。-
每次自增计数器值发生变化时,当前最大自增计数器值都会被写入重做日志,使其具有崩溃安全性。在恢复过程中,
InnoDB
会扫描重做日志以收集计数器值的变化,并将这些变化应用于内存中的表对象。有关
InnoDB
如何处理自增值的更多信息,请参阅第 17.6.1.6 节,“InnoDB 中的 AUTO_INCREMENT 处理”,以及 InnoDB AUTO_INCREMENT 计数器初始化。 -
当遇到索引树损坏时,
InnoDB
会将一个损坏标志写入重做日志,使得损坏标志具有崩溃安全性。InnoDB
还会在每次检查点时将内存中的损坏标志数据写入引擎私有系统表中。在恢复过程中,InnoDB
会从两个位置读取损坏标志,并在标记内存表和索引对象为损坏之前合并结果。 -
不建议删除重做日志以加快恢复速度,即使可以接受一些数据丢失。只有在干净关闭后,将
innodb_fast_shutdown
设置为0
或1
后才应考虑删除重做日志。
-
-
回滚未完成的事务
未完成的事务是在意外退出或快速关闭时处于活动状态的任何事务。回滚未完成事务所需的时间可能是事务被中断前活动时间的三到四倍,取决于服务器负载。
无法取消正在回滚的事务。在极端情况下,当预计回滚事务需要花费异常长的时间时,通过使用设置为
3
或更高的innodb_force_recovery
选项启动InnoDB
可能更快。请参阅第 17.21.3 节,“强制 InnoDB 恢复”。 -
更改缓冲区合并
将更改缓冲区(系统表空间的一部分)中的更改应用到辅助索引的叶页,因为索引页被读取到缓冲池中。
-
清理
删除对活动事务不再可见的已标记删除记录。
在重做日志应用后的步骤不依赖于重做日志(除了用于记录写入),并与正常处理并行执行。其中,只有不完整事务的回滚对于崩溃恢复是特殊的。插入缓冲区合并和清理是在正常处理期间执行的。
在重做日志应用之后,InnoDB
尽早尝试接受连接,以减少停机时间。作为崩溃恢复的一部分,InnoDB
回滚了在服务器退出时未提交或处于XA PREPARE
状态的事务。回滚由后台线程执行,并与新连接的事务并行执行。在回滚操作完成之前,新连接可能会与恢复的事务发生锁定冲突。
在大多数情况下,即使 MySQL 服务器在繁忙活动中意外关闭,恢复过程会自动发生,DBA 不需要采取任何行动。如果硬件故障或严重系统错误损坏了InnoDB
数据,MySQL 可能会拒绝启动。在这种情况下,请参阅第 17.21.3 节,“强制 InnoDB 恢复”。
有关二进制日志和InnoDB
崩溃恢复的信息,请参阅第 7.4.4 节,“二进制日志”。
在崩溃恢复期间的表空间发现
如果在恢复过程中,InnoDB
遇到自上次检查点以来写入的重做日志,则必须将重做日志应用于受影响的表空间。在恢复期间识别受影响表空间的过程称为表空间发现。
表空间发现依赖于innodb_directories
设置,该设置定义了在启动时扫描表空间文件的目录。innodb_directories
的默认设置为 NULL,但在 InnoDB 构建启动时要扫描的目录列表时,始终会将由innodb_data_home_dir
、innodb_undo_directory
和datadir
定义的目录附加到innodb_directories
参数值上。这些目录会被附加,无论是否明确指定了innodb_directories
设置。如果在重做日志中引用的任何表空间文件之前未发现,恢复将终止。
17.19 InnoDB 和 MySQL 复制
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-and-mysql-replication.html
可以以副本上的存储引擎与源端不同的方式使用复制。例如,您可以将对源端上的InnoDB
表的修改复制到副本上的MyISAM
表。有关更多信息,请参见第 19.4.4 节,“使用不同源和副本存储引擎的复制”。
有关设置副本的信息,请参见第 19.1.2.6 节,“设置副本”和第 19.1.2.5 节,“选择数据快照方法”。要创建一个新的副本而不关闭源端或现有副本,请使用 MySQL 企业备份产品。
在源端失败的事务不会影响复制。MySQL 复制基于二进制日志,MySQL 在其中写入修改数据的 SQL 语句。失败的事务(例如,由于外键违反或回滚而失败)不会被写入二进制日志,因此不会被发送到副本。参见第 15.3.1 节,“START TRANSACTION,COMMIT 和 ROLLBACK 语句”。
复制和级联。 仅当源端和副本上共享外键关系的表都使用InnoDB
时,源端上InnoDB
表的级联操作才会在副本上执行。无论您使用基于语句还是基于行的复制,这都是正确的。假设您已经开始了复制,然后在源端创建两个表,其中InnoDB
被定义为默认存储引擎,使用以下CREATE TABLE
语句:
CREATE TABLE fc1 (
i INT PRIMARY KEY,
j INT
);
CREATE TABLE fc2 (
m INT PRIMARY KEY,
n INT,
FOREIGN KEY ni (n) REFERENCES fc1 (i)
ON DELETE CASCADE
);
如果副本将MyISAM
定义为默认存储引擎,则在副本上创建相同的表,但它们使用MyISAM
存储引擎,并且FOREIGN KEY
选项被忽略。现在我们在源端的表中插入一些行:
source> INSERT INTO fc1 VALUES (1, 1), (2, 2);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
source> INSERT INTO fc2 VALUES (1, 1), (2, 2), (3, 1);
Query OK, 3 rows affected (0.19 sec)
Records: 3 Duplicates: 0 Warnings: 0
此时,在源端和副本上,fc1
表包含 2 行,fc2
表包含 3 行,如下所示:
source> SELECT * FROM fc1;
+---+------+
| i | j |
+---+------+
| 1 | 1 |
| 2 | 2 |
+---+------+
2 rows in set (0.00 sec)
source> SELECT * FROM fc2;
+---+------+
| m | n |
+---+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+---+------+
3 rows in set (0.00 sec)
replica> SELECT * FROM fc1;
+---+------+
| i | j |
+---+------+
| 1 | 1 |
| 2 | 2 |
+---+------+
2 rows in set (0.00 sec)
replica> SELECT * FROM fc2;
+---+------+
| m | n |
+---+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+---+------+
3 rows in set (0.00 sec)
现在假设您在源端执行以下DELETE
语句:
source> DELETE FROM fc1 WHERE i=1;
Query OK, 1 row affected (0.09 sec)
由于级联,源端的fc2
表现在只包含 1 行:
source> SELECT * FROM fc2;
+---+---+
| m | n |
+---+---+
| 2 | 2 |
+---+---+
1 row in set (0.00 sec)
然而,在副本上级联不会传播,因为在副本上对fc1
的DELETE
不会从fc2
中删除任何行。副本中的fc2
的副本仍然包含最初插入的所有行:
replica> SELECT * FROM fc2;
+---+---+
| m | n |
+---+---+
| 1 | 1 |
| 3 | 1 |
| 2 | 2 |
+---+---+
3 rows in set (0.00 sec)
这种差异是由于级联删除是由InnoDB
存储引擎内部处理的,这意味着没有任何更改被记录。
17.20 InnoDB memcached 插件
17.20.1 InnoDB memcached 插件的优势
17.20.2 InnoDB memcached 架构
17.20.3 设置 InnoDB memcached 插件
17.20.4 InnoDB memcached 多个 get 和范围查询支持
17.20.5 InnoDB memcached 插件的安全考虑
17.20.6 为 InnoDB memcached 插件编写应用程序
17.20.7 InnoDB memcached 插件和复制
17.20.8 InnoDB memcached 插件内部
17.20.9 InnoDB memcached 插件故障排除
重要提示
InnoDB
memcached插件在 MySQL 8.3.0 中被移除,在 MySQL 8.0.22 中被弃用。
InnoDB
memcached插件(daemon_memcached
)提供了一个集成的memcached守护程序,自动从InnoDB
表中存储和检索数据,将 MySQL 服务器转变为快速的“键-值存储”。您可以使用简单的get
、set
和incr
操作来代替在 SQL 中制定查询,避免与 SQL 解析和构建查询优化计划相关的性能开销。您也可以通过 SQL 访问相同的InnoDB
表,以便进行方便、复杂的查询、批量操作和传统数据库软件的其他优势。
这种“NoSQL 风格”的接口使用memcached API 加速数据库操作,让InnoDB
使用其缓冲池机制处理内存缓存。通过memcached操作修改的数据,如add
、set
和incr
,会存储到磁盘中的InnoDB
表中。memcached的简单性与InnoDB
的可靠性和一致性的结合,为用户提供了最佳的两全其美,如第 17.20.1 节“InnoDB memcached 插件的优势”中所解释的。有关架构概述,请参阅第 17.20.2 节“InnoDB memcached 架构”。
17.20.1 InnoDB memcached 插件的优势
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-benefits.html
本节概述了daemon_memcached
插件的优势。InnoDB
表和memcached的结合优于单独使用任一项。
-
直接访问
InnoDB
存储引擎可以避免 SQL 的解析和规划开销。 -
将memcached与 MySQL 服务器在同一进程空间中运行,避免了来回传递请求的网络开销。
-
使用memcached协议写入的数据会透明地写入到
InnoDB
表中,而不经过 MySQL SQL 层。您可以控制写入的频率,以实现在更新非关键数据时获得更高的原始性能。 -
通过memcached协议请求的数据会透明地从
InnoDB
表中查询,而不经过 MySQL SQL 层。 -
对相同数据的后续请求是从
InnoDB
缓冲池中提供的。缓冲池处理内存中的缓存。您可以使用InnoDB
配置选项调整数据密集型操作的性能。 -
数据可以是非结构化或结构化的,取决于应用程序的类型。您可以为数据创建新表,或使用现有表。
-
InnoDB
可以处理将多列值组合和分解为单个memcached项值,从而减少应用程序中所需的字符串解析和连接数量。例如,您可以将字符串值2|4|6|8
存储在memcached缓存中,并让InnoDB
根据分隔符字符拆分值,然后将结果存储在四个数值列中。 -
内存和磁盘之间的传输是自动处理的,简化了应用程序逻辑。
-
数据存储在 MySQL 数据库中,以防止崩溃、宕机和损坏。
-
您可以通过 SQL 访问底层的
InnoDB
表进行报告、分析、临时查询、批量加载、多步事务计算、集合操作(如并集和交集)以及其他适合 SQL 表达力和灵活性的操作。 -
通过在源服务器上结合使用
daemon_memcached
插件和 MySQL 复制,可以确保高可用性。 -
memcached与 MySQL 的集成提供了一种使内存中数据持久化的方式,因此您可以将其用于更重要的数据。您可以在应用程序中使用更多的
add
、incr
和类似的写操作,而不必担心数据丢失。您可以在不丢失缓存数据更新的情况下停止和启动memcached服务器。为防止意外宕机,您可以利用InnoDB
的崩溃恢复、复制和备份功能。 -
InnoDB
快速进行主键查找的方式非常适合memcached的单项查询。daemon_memcached
插件使用的直接、低级别的数据库访问路径对于键-值查找比等效的 SQL 查询更有效率。 -
memcached的序列化功能可以将复杂数据结构、二进制文件甚至代码块转换为可存储的字符串,为将这些对象存入数据库提供了简单的方法。
-
因为您可以通过 SQL 访问底层数据,所以可以生成报告、跨多个键进行搜索或更新,并在memcached数据上调用诸如
AVG()
和MAX()
之类的函数。所有这些操作在仅使用memcached时都是昂贵或复杂的。 -
您不需要在启动时手动加载数据到memcached中。当应用程序请求特定键时,值会自动从数据库中检索,并使用
InnoDB
缓冲池在内存中缓存。 -
因为memcached消耗的 CPU 相对较少,其内存占用量易于控制,所以它可以轻松地与同一系统上的 MySQL 实例一起运行。
-
因为数据一致性是由用于常规
InnoDB
表的机制强制执行的,所以您不必担心过时的memcached数据或在缺少键的情况下查询数据库的回退逻辑。
17.20.2 InnoDB memcached 架构
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-intro.html
InnoDB
memcached插件将memcached实现为直接访问InnoDB
存储引擎的 MySQL 插件守护程序,绕过 MySQL SQL 层。
以下图示说明了应用程序如何通过daemon_memcached
插件访问数据,与 SQL 相比。
图 17.4 集成 memcached 服务器的 MySQL 服务器
daemon_memcached
插件的特点:
-
memcached作为mysqld的守护插件。mysqld和memcached在同一进程空间中运行,对数据具有非常低的延迟访问。
-
直接访问
InnoDB
表,绕过 SQL 解析器、优化器,甚至 Handler API 层。 -
标准的memcached协议,包括基于文本的协议和二进制协议。
daemon_memcached
插件通过了memcapable命令的所有 55 个兼容性测试。 -
多列支持。您可以将多列映射到键值存储的“值”部分,列值由用户指定的分隔符字符分隔。
-
默认情况下,使用memcached协议直接读写数据到
InnoDB
,让 MySQL 使用InnoDB
缓冲池管理内存缓存。默认设置代表了高可靠性和数据库应用程序最少惊喜的组合。例如,默认设置避免了数据库端未提交数据,或者为memcached的get
请求返回陈旧数据。 -
高级用户可以将系统配置为传统的memcached服务器,所有数据仅缓存在memcached引擎(内存缓存)中,或者同时使用“memcached引擎”(内存缓存)和
InnoDB
memcached引擎(InnoDB
作为后端持久存储)的组合。 -
控制数据在
InnoDB
和memcached操作之间传递频率的配置选项包括innodb_api_bk_commit_interval
,daemon_memcached_r_batch_size
,和daemon_memcached_w_batch_size
。批量大小选项默认值为 1,以确保最大可靠性。 -
通过
daemon_memcached_option
配置参数指定memcached选项的能力。例如,您可以更改memcached监听的端口,减少最大同时连接数,更改键值对的最大内存大小,或为错误日志启用调试消息。 -
innodb_api_trx_level
配置选项控制由memcached处理的查询的事务隔离级别。虽然memcached没有事务的概念,但您可以使用此选项来控制memcached何时看到由daemon_memcached插件使用的表上发出的 SQL 语句引起的更改。默认情况下,innodb_api_trx_level
设置为READ UNCOMMITTED
。 -
innodb_api_enable_mdl
选项可用于在 MySQL 级别锁定表,以防止通过 SQL 接口对映射表进行 DDL 的删除或更改。如果没有锁定,表可以从 MySQL 层删除,但在memcached或其他用户停止使用之前,仍保留在InnoDB
存储中。“MDL”代表“metadata locking”。
17.20.3 设置 InnoDB memcached 插件
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-setup.html
本节描述了如何在 MySQL 服务器上设置daemon_memcached
插件。由于memcached守护程序与 MySQL 服务器紧密集成,以避免网络流量并最小化延迟,因此你需要在使用此功能的每个 MySQL 实例上执行此过程。
注意
在设置daemon_memcached
插件之前,请参考 Section 17.20.5, “InnoDB memcached 插件的安全注意事项” 以了解所需的安全程序,以防止未经授权的访问。
先决条件
-
daemon_memcached
插件仅支持 Linux、Solaris 和 macOS 平台。其他操作系统不受支持。 -
在从源代码构建 MySQL 时,你必须使用
-DWITH_INNODB_MEMCACHED=ON
构建选项。此构建选项在 MySQL 插件目录(plugin_dir
)中生成两个共享库,这些库是运行daemon_memcached
插件所需的:-
libmemcached.so
:memcached 守护程序插件到 MySQL。 -
innodb_engine.so
:memcached 的InnoDB
API 插件。
-
-
必须安装
libevent
。-
如果你没有从源代码构建 MySQL,那么
libevent
库不会包含在你的安装中。使用你的操作系统的安装方法来安装libevent
1.4.12 或更高版本。例如,根据操作系统的不同,你可能会使用apt-get
、yum
或port install
。例如,在 Ubuntu Linux 上,使用:sudo apt-get install libevent-dev
-
如果你从源代码发布中安装了 MySQL,
libevent
1.4.12 已经捆绑在包中,并位于 MySQL 源代码目录的顶层。如果你使用捆绑版本的libevent
,则无需采取任何操作。如果你想使用本地系统版本的libevent
,你必须使用-DWITH_LIBEVENT
构建选项设置为system
或yes
来构建 MySQL。
-
安装和配置 InnoDB memcached 插件
-
通过运行位于
*
MYSQL_HOME*/share
中的innodb_memcached_config.sql
配置脚本,配置daemon_memcached
插件以与InnoDB
表交互。此脚本安装了包含三个必需表(cache_policies
、config_options
和containers
)的innodb_memcache
数据库。它还在test
数据库中安装了demo_test
示例表。mysql> source *MYSQL_HOME*/share/innodb_memcached_config.sql
运行
innodb_memcached_config.sql
脚本是一次性操作。如果以后卸载并重新安装daemon_memcached
插件,表将保留在原位。mysql> USE innodb_memcache; mysql> SHOW TABLES; +---------------------------+ | Tables_in_innodb_memcache | +---------------------------+ | cache_policies | | config_options | | containers | +---------------------------+ mysql> USE test; mysql> SHOW TABLES; +----------------+ | Tables_in_test | +----------------+ | demo_test | +----------------+
在这些表中,
innodb_memcache.containers
表最重要。containers
表中的条目提供到InnoDB
表列的映射。每个使用daemon_memcached
插件的InnoDB
表都需要在containers
表中有一个条目。innodb_memcached_config.sql
脚本在containers
表中插入一个条目,为demo_test
表提供映射。它还在demo_test
表中插入一行数据。这些数据允许你在设置完成后立即验证安装。mysql> SELECT * FROM innodb_memcache.containers\G *************************** 1\. row *************************** name: aaa db_schema: test db_table: demo_test key_columns: c1 value_columns: c2 flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY mysql> SELECT * FROM test.demo_test; +----+------------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +----+------------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | +----+------------------+------+------+------+
有关
innodb_memcache
表和demo_test
示例表的更多信息,请参见 第 17.20.8 节,“InnoDB memcached 插件内部”。 -
通过运行
INSTALL PLUGIN
语句激活daemon_memcached
插件:mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
一旦插件安装完成,每次 MySQL 服务器重新启动时都会自动激活。
验证 InnoDB 和 memcached 设置
要验证 daemon_memcached
插件设置,使用 telnet 会话发出 memcached 命令。默认情况下,memcached 守护程序监听端口 11211。
-
从
test.demo_test
表中检索数据。demo_test
表中的单行数据具有键值AA
。telnet localhost 11211 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get AA VALUE AA 8 12 HELLO, HELLO END
-
使用
set
命令插入数据。set BB 10 0 16 GOODBYE, GOODBYE STORED
其中:
-
set
是存储值的命令 -
BB
是键 -
10
是操作的标志;memcached 忽略但客户端可能用于指示任何类型的信息;如果未使用,请指定0
-
0
是过期时间(TTL);如果未使用,请指定0
-
提供的值块的长度为
16
字节 -
GOODBYE, GOODBYE
是存储的值
-
-
通过连接到 MySQL 服务器并查询
test.demo_test
表来验证插入的数据是否存储在 MySQL 中。mysql> SELECT * FROM test.demo_test; +----+------------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +----+------------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | | BB | GOODBYE, GOODBYE | 10 | 1 | 0 | +----+------------------+------+------+------+
-
返回 telnet 会话并使用键
BB
检索之前插入的数据。get BB VALUE BB 10 16 GOODBYE, GOODBYE END quit
如果关闭 MySQL 服务器,也会关闭集成的 memcached 服务器,进一步尝试访问 memcached 数据会因连接错误而失败。通常情况下,此时 memcached 数据也会消失,当 memcached 重新启动时,你需要应用逻辑来重新加载数据。然而,InnoDB
memcached 插件会自动化这个过程。
当你重新启动 MySQL 时,get
操作会再次返回你在之前 memcached 会话中存储的键值对。当请求一个键并且相关值不在内存缓存中时,该值会自动从 MySQL test.demo_test
表中查询。
创建新表和列映射
此示例展示了如何使用 daemon_memcached
插件设置自己的 InnoDB
表。
-
创建一个
InnoDB
表。表必须具有具有唯一索引的键列。城市表的键列是city_id
,定义为主键。表还必须包括用于flags
,cas
和expiry
值的列。可能有一个或多个值列。city
表有三个值列(name
,state
,country
)。注意
列名没有特殊要求,只要向
innodb_memcache.containers
表添加有效映射即可。mysql> CREATE TABLE city ( city_id VARCHAR(32), name VARCHAR(1024), state VARCHAR(1024), country VARCHAR(1024), flags INT, cas BIGINT UNSIGNED, expiry INT, primary key(city_id) ) ENGINE=InnoDB;
-
向
innodb_memcache.containers
表添加一个条目,以便daemon_memcached
插件知道如何访问InnoDB
表。该条目必须满足innodb_memcache.containers
表的定义。有关每个字段的描述,请参见第 17.20.8 节,“InnoDB memcached 插件内部”。mysql> DESCRIBE innodb_memcache.containers; +------------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------------+--------------+------+-----+---------+-------+ | name | varchar(50) | NO | PRI | NULL | | | db_schema | varchar(250) | NO | | NULL | | | db_table | varchar(250) | NO | | NULL | | | key_columns | varchar(250) | NO | | NULL | | | value_columns | varchar(250) | YES | | NULL | | | flags | varchar(250) | NO | | 0 | | | cas_column | varchar(250) | YES | | NULL | | | expire_time_column | varchar(250) | YES | | NULL | | | unique_idx_name_on_key | varchar(250) | NO | | NULL | | +------------------------+--------------+------+-----+---------+-------+
城市表的
innodb_memcache.containers
表条目定义为:mysql> INSERT INTO `innodb_memcache`.`containers` ( `name`, `db_schema`, `db_table`, `key_columns`, `value_columns`, `flags`, `cas_column`, `expire_time_column`, `unique_idx_name_on_key`) VALUES ('default', 'test', 'city', 'city_id', 'name|state|country', 'flags','cas','expiry','PRIMARY');
-
为
containers.name
列指定default
,以将city
表配置为与daemon_memcached
插件一起使用的默认InnoDB
表。 -
多个
InnoDB
表列(name
,state
,country
)使用“|”分隔符映射到containers.value_columns
。 -
innodb_memcache.containers
表的flags
,cas_column
和expire_time_column
字段在使用daemon_memcached
插件的应用程序中通常不重要。但是,每个字段都需要指定一个指定的InnoDB
表列。在插入数据时,如果未使用这些列,请为这些列指定0
。
-
-
更新
innodb_memcache.containers
表后,重新启动daemon_memcache
插件以应用更改。mysql> UNINSTALL PLUGIN daemon_memcached; mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
-
使用 telnet,使用memcached的
set
命令向city
表插入数据。telnet localhost 11211 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. set B 0 0 22 BANGALORE|BANGALORE|IN STORED
-
使用 MySQL,查询
test.city
表以验证您插入的数据是否已存储。mysql> SELECT * FROM test.city; +---------+-----------+-----------+---------+-------+------+--------+ | city_id | name | state | country | flags | cas | expiry | +---------+-----------+-----------+---------+-------+------+--------+ | B | BANGALORE | BANGALORE | IN | 0 | 3 | 0 | +---------+-----------+-----------+---------+-------+------+--------+
-
使用 MySQL,向
test.city
表插入额外数据。mysql> INSERT INTO city VALUES ('C','CHENNAI','TAMIL NADU','IN', 0, 0 ,0); mysql> INSERT INTO city VALUES ('D','DELHI','DELHI','IN', 0, 0, 0); mysql> INSERT INTO city VALUES ('H','HYDERABAD','TELANGANA','IN', 0, 0, 0); mysql> INSERT INTO city VALUES ('M','MUMBAI','MAHARASHTRA','IN', 0, 0, 0);
注意
如果未使用,建议为
flags
,cas_column
和expire_time_column
字段指定值0
。 -
使用 telnet,发出memcached的
get
命令以检索使用 MySQL 插入的数据。get H VALUE H 0 22 HYDERABAD|TELANGANA|IN END
配置 InnoDB memcached 插件
传统的memcached
配置选项可以在 MySQL 配置文件或者mysqld启动字符串中指定,编码在daemon_memcached_option
配置参数的参数中。memcached
配置选项在插件加载时生效,这发生在每次启动 MySQL 服务器时。
例如,要使memcached监听端口 11222 而不是默认端口 11211,请将-p11222
指定为daemon_memcached_option
配置选项的参数:
mysqld .... --daemon_memcached_option="-p11222"
其他memcached选项可以编码在daemon_memcached_option
字符串中。例如,您可以指定选项来减少最大同时连接数,更改键值对的最大内存大小,或者启用错误日志的调试消息等。
也有一些特定于daemon_memcached
插件的配置选项。这些包括:
-
daemon_memcached_engine_lib_name
:指定实现InnoDB
memcached插件的共享库。默认设置为innodb_engine.so
。 -
daemon_memcached_engine_lib_path
:包含实现InnoDB
memcached插件的共享库的目录路径。默认值为 NULL,表示插件目录。 -
daemon_memcached_r_batch_size
:定义读操作(get
)的批量提交大小。它指定在进行多少次memcached读取操作后发生提交。daemon_memcached_r_batch_size
默认设置为 1,以便每个get
请求访问InnoDB
表中最近提交的数据,无论数据是通过memcached还是通过 SQL 更新的。当值大于 1 时,每次get
调用都会增加读操作计数器。flush_all
调用会重置读取和写入计数器。 -
daemon_memcached_w_batch_size
:定义写操作(set
、replace
、append
、prepend
、incr
、decr
等)的批量提交大小。daemon_memcached_w_batch_size
默认设置为 1,以防止在停机情况下丢失未提交的数据,并且使底层表上的 SQL 查询访问最新数据。当值大于 1 时,每次add
、set
、incr
、decr
和delete
调用都会增加写操作计数器。flush_all
调用会重置读取和写入计数器。
默认情况下,您不需要修改daemon_memcached_engine_lib_name
或daemon_memcached_engine_lib_path
。例如,如果您想要使用不同的存储引擎来memcached(如 NDB memcached引擎),则可以配置这些选项。
daemon_memcached
插件配置参数可以在 MySQL 配置文件中或在mysqld启动字符串中指定。它们在加载daemon_memcached
插件时生效。
在对daemon_memcached
插件配置进行更改时,重新加载插件以应用更改。要这样做,请发出以下语句:
mysql> UNINSTALL PLUGIN daemon_memcached;
mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
插件重新启动时会保留配置设置、所需表格和数据。
有关启用和禁用插件的更多信息,请参见第 7.6.1 节,“安装和卸载插件”。
17.20.4 InnoDB memcached 多个获取和范围查询支持
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-multiple-get-range-query.html
daemon_memcached
插件支持多个获取操作(在单个memcached查询中获取多个键值对)和范围查询。
多个获取操作
在单个memcached查询中获取多个键值对的能力通过减少客户端和服务器之间的通信流量来提高读取性能。对于InnoDB
,这意味着更少的事务和打开表操作。
以下示例演示了多个获取支持。该示例使用了创建新表和列映射中描述的test.city
表。
mysql> USE test;
mysql> SELECT * FROM test.city;
+---------+-----------+-------------+---------+-------+------+--------+
| city_id | name | state | country | flags | cas | expiry |
+---------+-----------+-------------+---------+-------+------+--------+
| B | BANGALORE | BANGALORE | IN | 0 | 1 | 0 |
| C | CHENNAI | TAMIL NADU | IN | 0 | 0 | 0 |
| D | DELHI | DELHI | IN | 0 | 0 | 0 |
| H | HYDERABAD | TELANGANA | IN | 0 | 0 | 0 |
| M | MUMBAI | MAHARASHTRA | IN | 0 | 0 | 0 |
+---------+-----------+-------------+---------+-------+------+--------+
运行get
命令以从city
表中检索所有值。结果以键值对序列返回。
telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get B C D H M
VALUE B 0 22
BANGALORE|BANGALORE|IN
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
VALUE M 0 21
MUMBAI|MAHARASHTRA|IN
END
在单个get
命令中检索多个值时,您可以切换表(使用@@*
containers.name*
符号)以检索第一个键的值,但不能为后续键切换表。例如,此示例中的表切换是有效的:
get @@aaa.AA BB
VALUE @@aaa.AA 8 12
HELLO, HELLO
VALUE BB 10 16
GOODBYE, GOODBYE
END
尝试在同一个get
命令中再次切换表以从不同表中检索键值不受支持。
通过多个获取操作检索的键的数量没有限制,但存储结果的内存限制为 128MB。
范围查询
对于范围查询,daemon_memcached
插件支持以下比较运算符:<
,>
,<=
,>=
。运算符前必须加上@
符号。当范围查询找到多个匹配的键值对时,结果以键值对序列返回。
以下示例演示了范围查询支持。这些示例使用了创建新表和列映射中描述的test.city
表。
mysql> SELECT * FROM test.city;
+---------+-----------+-------------+---------+-------+------+--------+
| city_id | name | state | country | flags | cas | expiry |
+---------+-----------+-------------+---------+-------+------+--------+
| B | BANGALORE | BANGALORE | IN | 0 | 1 | 0 |
| C | CHENNAI | TAMIL NADU | IN | 0 | 0 | 0 |
| D | DELHI | DELHI | IN | 0 | 0 | 0 |
| H | HYDERABAD | TELANGANA | IN | 0 | 0 | 0 |
| M | MUMBAI | MAHARASHTRA | IN | 0 | 0 | 0 |
+---------+-----------+-------------+---------+-------+------+--------+
打开 telnet 会话:
telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
要获取所有大于B
的值,请输入get @>B
:
get @>B
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
VALUE M 0 21
MUMBAI|MAHARASHTRA|IN
END
要获取所有小于M
的值,请输入get @<M
:
get @<M
VALUE B 0 22
BANGALORE|BANGALORE|IN
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
END
要获取所有小于或等于M
的值,请输入get @<=M
:
get @<=M
VALUE B 0 22
BANGALORE|BANGALORE|IN
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
VALUE M 0 21
MUMBAI|MAHARASHTRA|IN
要获取大于B
但小于M
的值,请输入get @>B@<M
:
get @>B@<M
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
END
最多可以解析两个比较运算符,一个是'小于'(@<
)或'小于或等于'(@<=
)运算符,另一个是'大于'(@>
)或'大于或等于'(@>=
)运算符。任何额外的运算符都被视为键的一部分。例如,如果您发出带有三个运算符的get
命令,则第三个运算符(@>C
)被视为键的一部分,get
命令将搜索小于M
且大于B@>C
的值。
get @<M@>B@>C
VALUE C 0 21
CHENNAI|TAMIL NADU|IN
VALUE D 0 14
DELHI|DELHI|IN
VALUE H 0 22
HYDERABAD|TELANGANA|IN
17.20.5 InnoDB memcached 插件的安全注意事项
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-security.html
注意
在将daemon_memcached
插件部署到生产服务器之前,请参考本节,甚至在包含敏感数据的 MySQL 实例上的测试服务器上。
因为memcached默认不使用身份验证机制,而可选的 SASL 身份验证不如传统的 DBMS 安全措施强大,因此只在使用daemon_memcached
插件的 MySQL 实例中保留非敏感数据,并将使用此配置的任何服务器与潜在入侵者隔离开。不要允许来自 Internet 的memcached访问这些服务器;只允许来自受防火墙保护的内部网络的访问,最好是来自可以限制成员资格的子网。
通过使用 SASL 对 memcached 进行密码保护
SASL 支持提供了保护 MySQL 数据库免受通过memcached客户端的未经身份验证访问的能力。本节介绍如何启用具有daemon_memcached
插件的 SASL。这些步骤几乎与为传统memcached服务器启用 SASL 执行的步骤相同。
SASL 代表“简单身份验证和安全层”,这是一种为基于连接的协议添加身份验证支持的标准。memcached在 1.4.3 版本中添加了 SASL 支持。
SASL 身份验证仅受二进制协议支持。
memcached客户端只能访问在innodb_memcache.containers
表中注册的InnoDB
表。尽管 DBA 可以对这些表施加访问限制,但无法控制通过memcached应用程序的访问。因此,提供了 SASL 支持以控制与daemon_memcached
插件关联的InnoDB
表的访问。
以下部分显示了如何构建、启用和测试启用 SASL 的daemon_memcached
插件。
构建和启用具有 InnoDB memcached 插件的 SASL
默认情况下,MySQL 发布包中不包含启用 SASL 的daemon_memcached
插件,因为启用 SASL 的daemon_memcached
插件需要使用 SASL 库构建memcached。要启用 SASL 支持,请下载 MySQL 源代码,并在下载 SASL 库后重新构建daemon_memcached
插件:
-
安装 SASL 开发和实用程序库。例如,在 Ubuntu 上,使用apt-get获取这些库:
sudo apt-get -f install libsasl2-2 sasl2-bin libsasl2-2 libsasl2-dev libsasl2-modules
-
通过将
ENABLE_MEMCACHED_SASL=1
添加到cmake选项中,可以构建具有 SASL 功能的daemon_memcached
插件共享库。memcached还提供简单的明文密码支持,这有助于测试。要启用简单的明文密码支持,请指定ENABLE_MEMCACHED_SASL_PWDB=1
cmake选项。总之,添加以下三个cmake选项:
cmake ... -DWITH_INNODB_MEMCACHED=1 -DENABLE_MEMCACHED_SASL=1 -DENABLE_MEMCACHED_SASL_PWDB=1
-
安装
daemon_memcached
插件,如第 17.20.3 节,“设置 InnoDB memcached 插件”所述。 -
配置一个用户名和密码文件。(此示例使用memcached简单明文密码支持。)
-
在文件中创建一个名为
testname
的用户,并将密码定义为testpasswd
:echo "testname:testpasswd:::::::" >/home/jy/memcached-sasl-db
-
配置
MEMCACHED_SASL_PWDB
环境变量,通知memcached
用户名称和密码文件的位置:export MEMCACHED_SASL_PWDB=/home/jy/memcached-sasl-db
-
通知
memcached
使用明文密码:echo "mech_list: plain" > /home/jy/work2/msasl/clients/memcached.conf export SASL_CONF_PATH=/home/jy/work2/msasl/clients
-
-
通过在
daemon_memcached_option
配置参数中编码memcached-S
选项,通过重新启动 MySQL 服务器启用 SASL:mysqld ... --daemon_memcached_option="-S"
-
为了测试设置,使用支持 SASL 的客户端,如SASL-enabled libmemcached。
memcp --servers=localhost:11211 --binary --username=testname --password=*password* myfile.txt memcat --servers=localhost:11211 --binary --username=testname --password=*password* myfile.txt
如果指定了不正确的用户名或密码,则操作将被拒绝,并显示
memcache error AUTHENTICATION FAILURE
消息。在这种情况下,请检查memcached-sasl-db
文件中设置的明文密码,以验证您提供的凭据是否正确。
还有其他测试使用memcached进行 SASL 身份验证的方法,但上述描述的方法是最直接的。
17.20.6 为 InnoDB memcached 插件编写应用程序
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-developing.html
17.20.6.1 为 InnoDB memcached 插件调整现有 MySQL 模式
17.20.6.2 为 InnoDB memcached 插件调整 memcached 应用程序
17.20.6.3 调整 InnoDB memcached 插件性能
17.20.6.4 控制 InnoDB memcached 插件的事务行为
17.20.6.5 将 DML 语句调整为 memcached 操作
17.20.6.6 在底层 InnoDB 表上执行 DML 和 DDL 语句
通常,为InnoDB
memcached插件编写应用程序涉及对使用 MySQL 或memcached API 的现有代码进行一定程度的重写或调整。
-
使用
daemon_memcached
插件,你不再需要在低性能机器上运行许多传统的memcached服务器,而是将与 MySQL 服务器数量相同的memcached服务器运行在具有大量磁盘存储和内存的相对高性能机器上。你可能会重用一些与memcached API 一起工作的现有代码,但由于不同的服务器配置,可能需要进行适应。 -
通过
daemon_memcached
插件存储的数据存储在VARCHAR
、TEXT
或BLOB
列中,并且必须转换为执行数值操作。你可以在应用程序端执行转换,或者在查询中使用CAST()
函数执行转换。 -
如果你来自数据库背景,你可能习惯于具有许多列的通用 SQL 表。memcached代码访问的表可能只有几列,甚至只有一个列用于保存数据值。
-
你可能需要调整应用程序的部分部分,以执行单行查询、插入、更新或删除操作,以提高代码关键部分的性能。通过
InnoDB
memcached接口执行的查询(读取)和 DML(写入)操作在性能上可以显著提高。写入操作的性能改进通常大于读取操作的性能改进,因此你可能需要专注于调整记录日志或记录网站上交互选择的代码。
以下部分将更详细地探讨这些要点。
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-porting-mysql.html
17.20.6.1 调整现有的 MySQL 模式以适应 InnoDB memcached 插件
在调整现有的 MySQL 模式或应用程序以使用daemon_memcached
插件时,请考虑这些memcached应用程序的方面:
-
memcached 键不能包含空格或换行符,因为这些字符在 ASCII 协议中用作分隔符。如果您使用包含空格的查找值,请在将其用作
add()
、set()
、get()
等调用中的键之前将其转换或哈希为无空格的值。尽管在使用二进制协议的程序中理论上允许这些字符作为键,但为了确保与广泛范围的客户端兼容性,您应限制键中使用的字符。 -
如果在
InnoDB
表中有一个短的数字主键列,请将其转换为字符串值,以将其用作memcached的唯一查找键。如果memcached服务器用于多个应用程序,或与多个InnoDB
表一起使用,请考虑修改名称以确保其唯一性。例如,在数字值之前添加表名,或数据库名和表名。注意
daemon_memcached
插件支持在具有INTEGER
定义为主键的映射InnoDB
表上进行插入和读取。 -
不能使用分区表来查询或存储使用memcached的数据。
-
memcached 协议将数字值作为字符串传递。为了在底层的
InnoDB
表中存储数字值,实现可以用于 SQL 函数如SUM()
或AVG()
的计数器,例如:-
使用足够字符的
VARCHAR
列来容纳预期最大数字的所有数字(如果适用,还有负号、小数点或两者的其他字符)。 -
在执行使用列值进行算术运算的任何查询中,使用
CAST()
函数将值从字符串转换为整数,或转换为其他数值类型。例如:# Alphabetic entries are returned as zero. SELECT CAST(c2 as unsigned integer) FROM demo_test; # Since there could be numeric values of 0, can't disqualify them. # Test the string values to find the ones that are integers, and average only those. SELECT AVG(cast(c2 as unsigned integer)) FROM demo_test WHERE c2 BETWEEN '0' and '9999999999'; # Views let you hide the complexity of queries. The results are already converted; # no need to repeat conversion functions and WHERE clauses each time. CREATE VIEW numbers AS SELECT c1 KEY, CAST(c2 AS UNSIGNED INTEGER) val FROM demo_test WHERE c2 BETWEEN '0' and '9999999999'; SELECT SUM(val) FROM numbers;
注意
结果集中的任何字母值在调用
CAST()
时都会转换为 0。在使用诸如AVG()
之类依赖于结果集中的行数的函数时,包括WHERE
子句以过滤非数字值。
-
-
如果用作键的
InnoDB
列可能具有超过 250 字节的值,请将该值哈希为少于 250 字节。 -
要在
daemon_memcached
插件中使用现有表,需在innodb_memcache.containers
表中为其定义一个条目。要使该表成为所有memcached请求的默认表,需在name
列中指定一个值为default
,然后重新启动 MySQL 服务器以使更改生效。如果您为不同类别的memcached数据使用多个表,请在innodb_memcache.containers
表中设置多个条目,其中name
值由您选择,然后在应用程序中发出形式为get @@*
name*
或set @@*
name*
的memcached请求,以指定用于后续memcached请求的表。要查看使用预定义的
test.demo_test
表之外的表的示例,请参阅示例 17.13,“使用自己的表与 InnoDB memcached 应用程序”。有关所需表布局,请参阅第 17.20.8 节,“InnoDB memcached 插件内部”。 -
要使用多个
InnoDB
表列值与memcached键值对,需在innodb_memcache.containers
条目的value_columns
字段中指定以逗号、分号、空格或竖线字符分隔的列名。例如,在value_columns
字段中指定col1,col2,col3
或col1|col2|col3
。在将字符串传递给memcached的
add
或set
调用之前,使用竖线字符作为分隔符将列值连接成单个字符串。字符串会自动解包为正确的列。每个get
调用返回一个包含以竖线字符分隔的列值的单个字符串。您可以使用适当的应用程序语法解包这些值。
示例 17.13 使用自己的表与 InnoDB memcached 应用程序
该示例展示了如何使用自己的表与一个使用memcached
进行数据操作的示例 Python 应用程序。
该示例假定daemon_memcached
插件已按照第 17.20.3 节,“设置 InnoDB memcached 插件”中描述的方式安装。还假定您的系统已配置为运行使用python-memcache
模块的 Python 脚本。
-
创建
multicol
表,其中存储包括人口、面积和驾驶侧数据(右侧为'R'
,左侧为'L'
)的国家信息。mysql> USE test; mysql> CREATE TABLE `multicol` ( `country` varchar(128) NOT NULL DEFAULT '', `population` varchar(10) DEFAULT NULL, `area_sq_km` varchar(9) DEFAULT NULL, `drive_side` varchar(1) DEFAULT NULL, `c3` int(11) DEFAULT NULL, `c4` bigint(20) unsigned DEFAULT NULL, `c5` int(11) DEFAULT NULL, PRIMARY KEY (`country`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
将记录插入
innodb_memcache.containers
表中,以便daemon_memcached
插件可以访问multicol
表。mysql> INSERT INTO innodb_memcache.containers (name,db_schema,db_table,key_columns,value_columns,flags,cas_column, expire_time_column,unique_idx_name_on_key) VALUES ('bbb','test','multicol','country','population,area_sq_km,drive_side', 'c3','c4','c5','PRIMARY'); mysql> COMMIT;
-
innodb_memcache.containers
记录中的multicol
表指定了一个name
值为'bbb'
,这是表标识符。注意
如果单个
InnoDB
表用于所有memcached应用程序,则可以将name
值设置为default
,以避免使用@@
符号切换表。 -
db_schema
列设置为test
,这是multicol
表所在的数据库的名称。 -
db_table
列设置为multicol
,这是InnoDB
表的名称。 -
key_columns
设置为唯一的country
列。country
列在multicol
表定义中被定义为主键。 -
不是使用单个
InnoDB
表列来保存复合数据值,数据分布在三个表列(population
,area_sq_km
和drive_side
)之间。为了容纳多个值列,value_columns
字段中指定了一个逗号分隔的列列表。在存储或检索值时,value_columns
字段中定义的列将被使用。 -
flags
,expire_time
和cas_column
字段的值基于demo.test
示例表中使用的值。在使用daemon_memcached
插件的应用程序中,这些字段通常不重要,因为 MySQL 会保持数据同步,不需要担心数据过期或变得陈旧。 -
unique_idx_name_on_key
字段设置为PRIMARY
,指的是在multicol
表中唯一的country
列上定义的主索引。
-
-
将示例 Python 应用程序复制到一个文件中。在本例中,示例脚本被复制到一个名为
multicol.py
的文件中。示例 Python 应用程序将数据插入
multicol
表,并检索所有键的数据,演示如何通过daemon_memcached
插件访问InnoDB
表。import sys, os import memcache def connect_to_memcached(): memc = memcache.Client(['127.0.0.1:11211'], debug=0); print "Connected to memcached." return memc def banner(message): print print "=" * len(message) print message print "=" * len(message) country_data = [ ("Canada","34820000","9984670","R"), ("USA","314242000","9826675","R"), ("Ireland","6399152","84421","L"), ("UK","62262000","243610","L"), ("Mexico","113910608","1972550","R"), ("Denmark","5543453","43094","R"), ("Norway","5002942","385252","R"), ("UAE","8264070","83600","R"), ("India","1210193422","3287263","L"), ("China","1347350000","9640821","R"), ] def switch_table(memc,table): key = "@@" + table print "Switching default table to '" + table + "' by issuing GET for '" + key + "'." result = memc.get(key) def insert_country_data(memc): banner("Inserting initial data via memcached interface") for item in country_data: country = item[0] population = item[1] area = item[2] drive_side = item[3] key = country value = "|".join([population,area,drive_side]) print "Key = " + key print "Value = " + value if memc.add(key,value): print "Added new key, value pair." else: print "Updating value for existing key." memc.set(key,value) def query_country_data(memc): banner("Retrieving data for all keys (country names)") for item in country_data: key = item[0] result = memc.get(key) print "Here is the result retrieved from the database for key " + key + ":" print result (m_population, m_area, m_drive_side) = result.split("|") print "Unpacked population value: " + m_population print "Unpacked area value : " + m_area print "Unpacked drive side value: " + m_drive_side if __name__ == '__main__': memc = connect_to_memcached() switch_table(memc,"bbb") insert_country_data(memc) query_country_data(memc) sys.exit(0)
示例 Python 应用程序注意事项:
-
运行应用程序不需要数据库授权,因为数据操作是通过memcached接口执行的。唯一需要的信息是memcached守护程序在本地系统上监听的端口号。
-
为确保应用程序使用
multicol
表,调用switch_table()
函数,该函数使用@@
符号执行虚拟的get
或set
请求。请求中的name
值为bbb
,这是在innodb_memcache.containers.name
字段中定义的multicol
表标识符。在实际应用程序中可能会使用更具描述性的
name
值。这个例子只是说明了在get @@...
请求中指定了一个表标识符,而不是表名。 -
用于插入和查询数据的实用函数演示了如何将 Python 数据结构转换为用于通过
add
或set
请求将数据发送到 MySQL 的管道分隔值,以及如何解压get
请求返回的管道分隔值。只有在将单个memcached值映射到多个 MySQL 表列时才需要进行这种额外处理。
-
-
运行示例 Python 应用程序。
$> python multicol.py
如果成功,示例应用程序将返回以下输出:
Connected to memcached. Switching default table to 'bbb' by issuing GET for '@@bbb'. ============================================== Inserting initial data via memcached interface ============================================== Key = Canada Value = 34820000|9984670|R Added new key, value pair. Key = USA Value = 314242000|9826675|R Added new key, value pair. Key = Ireland Value = 6399152|84421|L Added new key, value pair. Key = UK Value = 62262000|243610|L Added new key, value pair. Key = Mexico Value = 113910608|1972550|R Added new key, value pair. Key = Denmark Value = 5543453|43094|R Added new key, value pair. Key = Norway Value = 5002942|385252|R Added new key, value pair. Key = UAE Value = 8264070|83600|R Added new key, value pair. Key = India Value = 1210193422|3287263|L Added new key, value pair. Key = China Value = 1347350000|9640821|R Added new key, value pair. ============================================ Retrieving data for all keys (country names) ============================================ Here is the result retrieved from the database for key Canada: 34820000|9984670|R Unpacked population value: 34820000 Unpacked area value : 9984670 Unpacked drive side value: R Here is the result retrieved from the database for key USA: 314242000|9826675|R Unpacked population value: 314242000 Unpacked area value : 9826675 Unpacked drive side value: R Here is the result retrieved from the database for key Ireland: 6399152|84421|L Unpacked population value: 6399152 Unpacked area value : 84421 Unpacked drive side value: L Here is the result retrieved from the database for key UK: 62262000|243610|L Unpacked population value: 62262000 Unpacked area value : 243610 Unpacked drive side value: L Here is the result retrieved from the database for key Mexico: 113910608|1972550|R Unpacked population value: 113910608 Unpacked area value : 1972550 Unpacked drive side value: R Here is the result retrieved from the database for key Denmark: 5543453|43094|R Unpacked population value: 5543453 Unpacked area value : 43094 Unpacked drive side value: R Here is the result retrieved from the database for key Norway: 5002942|385252|R Unpacked population value: 5002942 Unpacked area value : 385252 Unpacked drive side value: R Here is the result retrieved from the database for key UAE: 8264070|83600|R Unpacked population value: 8264070 Unpacked area value : 83600 Unpacked drive side value: R Here is the result retrieved from the database for key India: 1210193422|3287263|L Unpacked population value: 1210193422 Unpacked area value : 3287263 Unpacked drive side value: L Here is the result retrieved from the database for key China: 1347350000|9640821|R Unpacked population value: 1347350000 Unpacked area value : 9640821 Unpacked drive side value: R
-
查询
innodb_memcache.containers
表以查看您之前为multicol
表插入的记录。第一条记录是在初始daemon_memcached
插件设置期间创建的demo_test
表的示例条目。第二条记录是您为multicol
表插入的条目。mysql> SELECT * FROM innodb_memcache.containers\G *************************** 1\. row *************************** name: aaa db_schema: test db_table: demo_test key_columns: c1 value_columns: c2 flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY *************************** 2\. row *************************** name: bbb db_schema: test db_table: multicol key_columns: country value_columns: population,area_sq_km,drive_side flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY
-
查询
multicol
表以查看样本 Python 应用程序插入的数据。这些数据可供 MySQL 查询,演示了如何使用 SQL 或通过应用程序(使用适当的 MySQL 连接器或 API)访问相同的数据。mysql> SELECT * FROM test.multicol; +---------+------------+------------+------------+------+------+------+ | country | population | area_sq_km | drive_side | c3 | c4 | c5 | +---------+------------+------------+------------+------+------+------+ | Canada | 34820000 | 9984670 | R | 0 | 11 | 0 | | China | 1347350000 | 9640821 | R | 0 | 20 | 0 | | Denmark | 5543453 | 43094 | R | 0 | 16 | 0 | | India | 1210193422 | 3287263 | L | 0 | 19 | 0 | | Ireland | 6399152 | 84421 | L | 0 | 13 | 0 | | Mexico | 113910608 | 1972550 | R | 0 | 15 | 0 | | Norway | 5002942 | 385252 | R | 0 | 17 | 0 | | UAE | 8264070 | 83600 | R | 0 | 18 | 0 | | UK | 62262000 | 243610 | L | 0 | 14 | 0 | | USA | 314242000 | 9826675 | R | 0 | 12 | 0 | +---------+------------+------------+------------+------+------+------+
注意
在定义被视为数字的列的长度时,始终要允许足够的大小来容纳必要的数字、小数点、符号字符、前导零等。对于像
VARCHAR
这样的字符串列中的值过长,通过删除一些字符来截断,可能会产生荒谬的数值。 -
可选地,在存储memcached数据的
InnoDB
表上运行报告类型的查询。您可以通过 SQL 查询生成报告,对任何列执行计算和测试,而不仅仅是
country
键列。 (因为以下示例仅使用了少数国家的数据,所以数字仅供说明目的。)以下查询返回驾驶方向为右侧的国家的平均人口和以“U”开头的国家的平均大小:mysql> SELECT AVG(population) FROM multicol WHERE drive_side = 'R'; +-------------------+ | avg(population) | +-------------------+ | 261304724.7142857 | +-------------------+ mysql> SELECT SUM(area_sq_km) FROM multicol WHERE country LIKE 'U%'; +-----------------+ | sum(area_sq_km) | +-----------------+ | 10153885 | +-----------------+
因为
population
和area_sq_km
列存储的是字符数据而不是强类型的数值数据,所以诸如AVG()
和SUM()
之类的函数会先将每个值转换为数字。这种方法不适用于诸如<
或>
之类的运算符,例如,当比较基于字符的值时,9 > 1000
,这与ORDER BY population DESC
这样的子句所期望的不符。为了获得最准确的类型处理,请对将数值列转换为适当类型的视图执行查询。这种技术使您可以从数据库应用程序发出简单的SELECT *
查询,同时确保转换、过滤和排序是正确的。以下示例显示了一个视图,可以查询以按人口降序排列的前三个国家,结果反映了multicol
表中的最新数据,并将人口和面积数字视为数字:mysql> CREATE VIEW populous_countries AS SELECT country, cast(population as unsigned integer) population, cast(area_sq_km as unsigned integer) area_sq_km, drive_side FROM multicol ORDER BY CAST(population as unsigned integer) DESC LIMIT 3; mysql> SELECT * FROM populous_countries; +---------+------------+------------+------------+ | country | population | area_sq_km | drive_side | +---------+------------+------------+------------+ | China | 1347350000 | 9640821 | R | | India | 1210193422 | 3287263 | L | | USA | 314242000 | 9826675 | R | +---------+------------+------------+------------+ mysql> DESC populous_countries; +------------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+---------------------+------+-----+---------+-------+ | country | varchar(128) | NO | | | | | population | bigint(10) unsigned | YES | | NULL | | | area_sq_km | int(9) unsigned | YES | | NULL | | | drive_side | varchar(1) | YES | | NULL | | +------------+---------------------+------+-----+---------+-------+
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-porting-memcached.html
17.20.6.2 调整 memcached 应用以适配 InnoDB memcached 插件
在将现有的memcached应用程序调整为使用daemon_memcached
插件时,请考虑 MySQL 和InnoDB
表的这些方面:
-
如果键值长于几个字节,最好在
InnoDB
表的主键上使用数值自增列,并在包含memcached键值的列上创建唯一的二级索引可能更有效。这是因为如果主键值按排序顺序添加(就像使用自增值一样),InnoDB
在大规模插入时表现最佳。主键值包含在二级索引中,如果主键是长字符串值,则会占用不必要的空间。 -
如果您使用memcached存储多种不同类别的信息,请考虑为每种数据类型设置单独的
InnoDB
表。在innodb_memcache.containers
表中定义额外的表标识符,并使用@@*
table_id*.*
key*
的表示法来存储和检索来自不同表的项目。物理上划分不同类型的信息允许您调整每个表的特性,以实现最佳的空间利用率、性能和可靠性。例如,您可以为保存博客文章的表启用压缩,但不为保存缩略图图像的表启用。您可能更频繁地备份一个表,因为它包含关键数据。您可能在经常用于生成报告的表上创建额外的二级索引。 -
最好为与daemon_memcached插件一起使用的表定义一个稳定的表定义,并永久保留这些表。对
innodb_memcache.containers
表的更改将在下次查询innodb_memcache.containers
表时生效。容器表中的条目在启动时被处理,并且在使用@@
表示法请求未识别的表标识符(由containers.name
定义)时会被查询。因此,只要使用相关的表标识符,新条目就会立即可见,但对现有条目的更改需要在生效之前重新启动服务器。 -
当您使用默认的
innodb_only
缓存策略时,对add()
、set()
、incr()
等的调用可能会成功,但仍会触发调试消息,如while expecting 'STORED', got unexpected response 'NOT_STORED
。调试消息的出现是因为新值和更新值直接发送到InnoDB
表,而不保存在内存缓存中,这是由于innodb_only
缓存策略导致的。
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-tuning.html
17.20.6.3 调整 InnoDB memcached 插件性能
因为使用InnoDB
与memcached结合涉及将所有数据写入磁盘,无论是立即还是稍后,所以原始性能预计会比单独使用memcached略慢。在使用InnoDB
memcached插件时,将memcached操作的调整目标集中在实现比等效 SQL 操作更好的性能上。
基准测试表明,使用memcached接口的查询和 DML 操作(插入、更新和删除)比传统 SQL 更快。DML 操作通常会看到更大的改进。因此,首先考虑调整写入密集型应用程序以使用memcached接口。还要考虑优先适应使用快速、轻量级机制但缺乏可靠性的写入密集型应用程序。
调整 SQL 查询
最适合简单GET
请求的查询类型是具有单个子句或WHERE
子句中一组AND
条件的查询:
SQL:
SELECT col FROM tbl WHERE key = 'key_value';
memcached:
get key_value
SQL:
SELECT col FROM tbl WHERE col1 = val1 and col2 = val2 and col3 = val3;
memcached:
# Since you must always know these 3 values to look up the key,
# combine them into a unique string and use that as the key
# for all ADD, SET, and GET operations.
key_value = val1 + ":" + val2 + ":" + val3
get key_value
SQL:
SELECT 'key exists!' FROM tbl
WHERE EXISTS (SELECT col1 FROM tbl WHERE KEY = 'key_value') LIMIT 1;
memcached:
# Test for existence of key by asking for its value and checking if the call succeeds,
# ignoring the value itself. For existence checking, you typically only store a very
# short value such as "1".
get key_value
利用系统内存
为了获得最佳性能,请在配置为典型数据库服务器的机器上部署daemon_memcached
插件,其中大部分系统 RAM 专用于InnoDB
缓冲池,通过innodb_buffer_pool_size
配置选项。对于具有多千兆字节缓冲池的系统,考虑提高innodb_buffer_pool_instances
的值,以获得大多数操作涉及已缓存在内存中的数据时的最大吞吐量。
减少冗余 I/O
InnoDB
有许多设置选项,让您在发生崩溃时可以选择高可靠性,同时在高写入工作负载期间减少 I/O 开销。例如,考虑将innodb_doublewrite
设置为0
,将innodb_flush_log_at_trx_commit
设置为2
。使用不同的innodb_flush_method
设置来衡量性能。
若要减少或调整表操作的 I/O 的其他方法,请参阅第 10.5.8 节,“优化 InnoDB 磁盘 I/O”。
减少事务开销
daemon_memcached_r_batch_size
和daemon_memcached_w_batch_size
的默认值为 1,旨在获得最大的结果可靠性和存储或更新数据的安全性。
根据应用程序的类型,您可能会增加这两个设置中的一个或两个,以减少频繁提交操作的开销。在繁忙的系统上,您可能会增加daemon_memcached_r_batch_size
的值,知道通过 SQL 对数据的更改可能不会立即对memcached可见(也就是说,直到处理了N
次get
操作)。在处理每个写操作都必须可靠存储的数据时,将daemon_memcached_w_batch_size
设置为1
。在处理仅用于统计分析的大量更新时,可以增加该设置,其中在意外退出时丢失最后N
次更新是可以接受的风险。
例如,想象一个监视穿过繁忙桥梁的交通的系统,每天记录大约 10 万辆车辆的数据。如果应用程序计算不同类型的车辆以分析交通模式,将daemon_memcached_w_batch_size
从1
更改为100
可以将提交操作的 I/O 开销减少 99%。在发生故障时,最多会丢失 100 条记录,这可能是可以接受的误差范围。如果应用程序执行每辆车的自动收费,您将把daemon_memcached_w_batch_size
设置为1
,以确保每个收费记录立即保存到磁盘。
由于InnoDB
在磁盘上组织memcached键值的方式,如果要创建大量键,则在应用程序中按键值对数据项进行排序并按排序顺序add
它们可能比以任意顺序创建键更快。
memslap命令是常规memcached分发的一部分,但不包括在daemon_memcached
插件中,可用于对不同配置进行基准测试。它还可用于生成样本键值对,以在您自己的基准测试中使用。
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-txn.html
17.20.6.4 控制 InnoDB memcached 插件的事务行为
与传统的memcached不同,daemon_memcached
插件允许您控制通过add
、set
、incr
等调用生成的数据值的耐久性。默认情况下,通过memcached接口写入的数据会存储到磁盘,并且调用get
会从磁盘返回最新的值。尽管默认行为并不提供最佳的原始性能,但与InnoDB
表的 SQL 接口相比,仍然快速。
随着您使用daemon_memcached
插件的经验增加,您可以考虑放宽非关键数据类的耐久性设置,以便在发生故障时可能会丢失一些更新的值,或者返回略有过时的数据。
提交频率
耐久性和原始性能之间的一个权衡是新数据和更改数据的提交频率。如果数据很关键,应立即提交,以便在意外退出或故障时安全。如果数据不那么关键,例如在意外退出后重置的计数器或您可以承受丢失的日志数据,您可能更喜欢更少的提交频率可用的更高原始吞吐量。
当memcached操作在底层InnoDB
表中插入、更新或删除数据时,如果daemon_memcached_w_batch_size=1
,更改可能会立即提交到InnoDB
表中,或者稍后一段时间(如果daemon_memcached_w_batch_size
的值大于 1)。在任何情况下,更改都无法回滚。如果您增加daemon_memcached_w_batch_size
的值以避免在繁忙时期产生高 I/O 开销,当工作负载减少时,提交可能变得不频繁。作为一项安全措施,后台线程会定期自动提交通过memcached API 进行的更改。这个间隔由innodb_api_bk_commit_interval
配置选项控制,默认设置为5
秒。
当memcached操作在底层InnoDB
表中插入或更新数据时,由于新值仍然保留在内存缓存中,即使尚未在 MySQL 端提交,其他memcached请求立即可以看到更改的数据。
事务隔离
当 memcached 操作(如 get
或 incr
)导致基础 InnoDB
表上的查询或 DML 操作时,您可以控制操作是否看到表中最新写入的数据,仅看到已提交的数据,或事务隔离级别的其他变化。使用 innodb_api_trx_level
配置选项来控制此功能。此选项指定的数字值对应于隔离级别,如 REPEATABLE READ
。有关其他设置的信息,请参阅 innodb_api_trx_level
选项的描述。
严格的隔离级别确保您检索的数据不会被回滚或突然更改,导致后续查询返回不同的值。然而,严格的隔离级别需要更大的锁定开销,可能会导致等待。对于不使用长时间事务的 NoSQL 风格应用程序,通常可以使用默认隔离级别或切换到较不严格的隔禅级别。
禁用 memcached 的 DML 操作的行锁。
当 memcached 请求通过 daemon_memcached
插件导致对 InnoDB
表的查询或 DML 操作时,可以使用 innodb_api_disable_rowlock
选项来禁用行锁。默认情况下,innodb_api_disable_rowlock
设置为 OFF
,这意味着 memcached 请求行锁用于 get
和 set
操作。当 innodb_api_disable_rowlock
设置为 ON
时,memcached 请求表锁而不是行锁。
innodb_api_disable_rowlock
选项不是动态的。必须在启动时在 mysqld 命令行上指定,或在 MySQL 配置文件中输入。
允许或禁止 DDL。
默认情况下,可以在 daemon_memcached
插件使用的表上执行 DDL 操作,如 ALTER TABLE
。为避免这些表用于高吞吐量应用程序时潜在的减速,启用 innodb_api_enable_mdl
来禁用这些表上的 DDL 操作。当通过 memcached 和 SQL 访问相同的表时,此选项不太合适,因为它会阻止对表进行 CREATE INDEX
语句的操作,这对运行报表查询可能很重要。
将数据存储在磁盘、内存中,或两者兼而有之。
innodb_memcache.cache_policies
表指定是否将通过 memcached 接口写入的数据存储到磁盘(innodb_only
,默认);仅存��在内存中,如传统的 memcached(cache_only
);或两者兼而有之(caching
)。
使用caching
设置,如果memcached在内存中找不到一个键,它会在InnoDB
表中搜索该值。在caching
设置下返回的get
调用的值可能已经过时,如果这些值在InnoDB
表中更新但尚未从内存缓存中过期。
缓存策略可以独立设置为get
、set
(包括incr
和decr
)、delete
和flush
操作。
例如,您可以允许get
和set
操作同时查询或更新表和memcached内存缓存(使用caching
设置),同时使delete
、flush
或两者仅在内存副本上操作(使用cache_only
设置)。这样,删除或刷新项目仅会使项目从缓存中过期,并且下次请求项目时将从InnoDB
表中返回最新值。
mysql> SELECT * FROM innodb_memcache.cache_policies;
+--------------+-------------+-------------+---------------+--------------+
| policy_name | get_policy | set_policy | delete_policy | flush_policy |
+--------------+-------------+-------------+---------------+--------------+
| cache_policy | innodb_only | innodb_only | innodb_only | innodb_only |
+--------------+-------------+-------------+---------------+--------------+
mysql> UPDATE innodb_memcache.cache_policies SET set_policy = 'caching'
WHERE policy_name = 'cache_policy';
innodb_memcache.cache_policies
的值只在启动时读取。在更改此表中的值后,卸载并重新安装daemon_memcached
插件以确保更改生效。
mysql> UNINSTALL PLUGIN daemon_memcached;
mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-dml.html
17.20.6.5 将 DML 语句调整为 memcached 操作
基准测试表明,daemon_memcached
插件加速了 DML 操作(插入、更新和删除)比加速查询更多。因此,考虑将初始开发工作重点放在写入密集型且 I/O 限制的应用程序上,并寻找机会在新的写入密集型应用程序中使用带有 daemon_memcached
插件的 MySQL。
单行 DML 语句是最容易转换为 memcached
操作的语句类型。INSERT
变为 add
,UPDATE
变为 set
,incr
或 decr
,而 DELETE
变为 delete
。这些操作通过 memcached 接口发出时,保证只影响一行,因为 key
在表内是唯一的。
在以下的 SQL 示例中,t1
指的是基于 innodb_memcache.containers
表中配置的 memcached 操作所使用的表。key
指的是列在 key_columns
下列出的列,val
指的是列在 value_columns
下列出的列。
INSERT INTO t1 (key,val) VALUES (*some_key*,*some_value*);
SELECT val FROM t1 WHERE key = *some_key*;
UPDATE t1 SET val = *new_value* WHERE key = *some_key*;
UPDATE t1 SET val = val + x WHERE key = *some_key*;
DELETE FROM t1 WHERE key = *some_key*;
下面的 TRUNCATE TABLE
和 DELETE
语句,用于从表中删除所有行,对应于 flush_all
操作,其中 t1
被配置为 memcached 操作的表,就像前面的示例中一样。
TRUNCATE TABLE t1;
DELETE FROM t1;
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-ddl.html
17.20.6.6 在底层 InnoDB 表上执行 DML 和 DDL 语句
您可以通过标准 SQL 接口访问底层的InnoDB
表(默认为test.demo_test
)。但是,存在一些限制:
-
当查询通过memcached接口访问的表时,请记住memcached操作可以配置为定期提交,而不是在每次写操作后立即提交。此行为由
daemon_memcached_w_batch_size
选项控制。如果此选项设置为大于1
的值,请使用READ UNCOMMITTED
查询以查找刚刚插入的行。mysql> SET SESSSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; mysql> SELECT * FROM demo_test; +------+------+------+------+-----------+------+------+------+------+------+------+ | cx | cy | c1 | cz | c2 | ca | CB | c3 | cu | c4 | C5 | +------+------+------+------+-----------+------+------+------+------+------+------+ | NULL | NULL | a11 | NULL | 123456789 | NULL | NULL | 10 | NULL | 3 | NULL | +------+------+------+------+-----------+------+------+------+------+------+------+
-
当使用 SQL 修改通过memcached接口访问的表时,您可以配置memcached操作定期启动新事务,而不是每次读操作都启动事务。此行为由
daemon_memcached_r_batch_size
选项控制。如果此选项设置为大于1
的值,则使用 SQL 对表进行的更改不会立即对memcached操作可见。 -
对于事务中的所有操作,
InnoDB
表都会被 IS(意向共享)或 IX(意向排他)锁定。如果您将daemon_memcached_r_batch_size
和daemon_memcached_w_batch_size
从默认值1
大幅增加,那么表在每个操作之间很可能被锁定,从而阻止对表的 DDL 语句的执行。
17.20.7 InnoDB memcached 插件和复制
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-replication.html
因为daemon_memcached
插件支持 MySQL 的二进制日志,源服务器通过memcached接口可以进行备份复制,平衡读取工作负载,并实现高可用性。所有memcached命令都支持二进制日志记录。
您无需在副本服务器上设置daemon_memcached
插件。此配置的主要优势是增加源端的写入吞吐量。复制机制的速度不受影响。
以下各节显示了在使用daemon_memcached
插件进行 MySQL 复制时如何使用二进制日志功能。假定您已完成第 17.20.3 节“设置 InnoDB memcached 插件”中描述的设置。
启用 InnoDB memcached 二进制日志
-
要在 MySQL 的二进制日志中使用
daemon_memcached
插件,请在源服务器上启用innodb_api_enable_binlog
配置选项。此选项只能在服务器启动时设置。您还必须在源服务器上使用--log-bin
选项启用 MySQL 的二进制日志。您可以将这些选项添加到 MySQL 配置文件中,或者在mysqld命令行中添加。mysqld ... --log-bin -–innodb_api_enable_binlog=1
-
配置源服务器和副本服务器,如第 19.1.2 节“基于二进制日志文件位置的复制设置”中所述。
-
使用mysqldump创建源数据快照,并将快照同步到副本服务器。
source $> mysqldump --all-databases --lock-all-tables > dbdump.db replica $> mysql < dbdump.db
-
在源服务器上,执行
SHOW MASTER STATUS
以获取源二进制日志坐标。mysql> SHOW MASTER STATUS;
-
在副本服务器上,使用
CHANGE REPLICATION SOURCE TO
语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO
语句(MySQL 8.0.23 之前)设置使用源二进制日志坐标的副本服务器。mysql> CHANGE MASTER TO MASTER_HOST='localhost', MASTER_USER='root', MASTER_PASSWORD='', MASTER_PORT = 13000, MASTER_LOG_FILE='0.000001, MASTER_LOG_POS=114; Or from MySQL 8.0.23: mysql> CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost', SOURCE_USER='root', SOURCE_PASSWORD='', SOURCE_PORT = 13000, SOURCE_LOG_FILE='0.000001, SOURCE_LOG_POS=114;
-
启动副本。
mysql> START SLAVE; Or from MySQL 8.0.22: mysql> START REPLICA;
如果错误日志输出类似于以下内容,则副本已准备好进行复制。
2013-09-24T13:04:38.639684Z 49 [Note] Replication I/O thread: connected to source 'root@localhost:13000', replication started in log '0.000001' at position 114
测试 InnoDB memcached 复制配置
该示例演示了如何使用memcached和 telnet 测试InnoDB memcached复制配置,以插入、更新和删除数据。使用 MySQL 客户端验证源服务器和副本服务器上的结果。
该示例使用了innodb_memcached_config.sql
配置脚本在daemon_memcached
插件的初始设置期间创建的demo_test
表。demo_test
表包含一个示例记录。
-
使用
set
命令插入一个具有键test1
、标志值10
、过期值0
、cas 值 1 和值t1
的记录。telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set test1 10 0 1 t1 STORED
-
在源服务器上,检查记录是否插入到
demo_test
表中。假设demo_test
表之前未被修改,应该有两条记录。一个具有键AA
的示例记录,以及刚刚插入的具有键test1
的记录。c1
列映射到键,c2
列映射到值,c3
列映射到标志值,c4
列映射到 cas 值,c5
列映射到过期时间。过期时间设置为 0,因为未使用。mysql> SELECT * FROM test.demo_test; +-------+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +-------+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | | test1 | t1 | 10 | 1 | 0 | +-------+--------------+------+------+------+
-
检查验证相同记录是否被复制到副本服务器。
mysql> SELECT * FROM test.demo_test; +-------+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +-------+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | | test1 | t1 | 10 | 1 | 0 | +-------+--------------+------+------+------+
-
使用
set
命令将键更新为new
的值。telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set test1 10 0 2 new STORED
更新被复制到副本服务器(注意
cas
值也被更新)。mysql> SELECT * FROM test.demo_test; +-------+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +-------+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | | test1 | new | 10 | 2 | 0 | +-------+--------------+------+------+------+
-
使用
delete
命令删除test1
记录。telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. delete test1 DELETED
当
delete
操作被复制到副本时,副本上的test1
记录也被删除。mysql> SELECT * FROM test.demo_test; +----+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +----+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | +----+--------------+------+------+------+
-
使用
flush_all
命令从表中删除所有行。telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. flush_all OK
mysql> SELECT * FROM test.demo_test; Empty set (0.00 sec)
-
使用 telnet 连接到源服务器并输入两条新记录。
telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]' set test2 10 0 4 again STORED set test3 10 0 5 again1 STORED
-
确认两条记录是否被复制到副本服务器。
mysql> SELECT * FROM test.demo_test; +-------+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +-------+--------------+------+------+------+ | test2 | again | 10 | 4 | 0 | | test3 | again1 | 10 | 5 | 0 | +-------+--------------+------+------+------+
-
使用
flush_all
命令从表中删除所有行。telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. flush_all OK
-
检查确保
flush_all
操作在副本服务器上被复制。mysql> SELECT * FROM test.demo_test; Empty set (0.00 sec)
InnoDB memcached二进制日志注释
二进制日志格式:
-
大多数memcached操作都映射到 DML 语句(类似于插入、删除、更新)。由于 MySQL 服务器没有实际的 SQL 语句在处理,所有memcached命令(除了
flush_all
)使用基于行的复制(RBR)日志记录,这与任何服务器binlog_format
设置无关。 -
memcached的
flush_all
命令映射到 MySQL 5.7 及更早版本的TRUNCATE TABLE
命令。由于 DDL 命令只能使用基于语句的日志记录,flush_all
命令通过发送TRUNCATE TABLE
语句来复制。在 MySQL 8.0 及更高版本中,flush_all
映射到DELETE
,但仍通过发送TRUNCATE TABLE
语句来复制。
事务:
-
事务的概念通常不是memcached应用的一部分。为了性能考虑,
daemon_memcached_r_batch_size
和daemon_memcached_w_batch_size
用于控制读取和写入事务的批处理大小。这些设置不影响复制。在底层InnoDB
表上的每个 SQL 操作在成功完成后被复制。 -
daemon_memcached_w_batch_size
的默认值为1
,这意味着每个memcached写操作立即提交。这个默认设置会产生一定的性能开销,以避免在源服务器和副本服务器上可见的数据不一致。复制的记录在副本服务器上始终立即可用。如果将daemon_memcached_w_batch_size
设置为大于1
的值,则通过memcached插入或更新的记录在源服务器上不会立即可见;在提交之前在源服务器上查看记录,请发出SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
。
17.20.8 InnoDB memcached 插件内部
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-internals.html
InnoDB memcached 插件的 InnoDB API
InnoDB
memcached引擎通过InnoDB
API 访问InnoDB
,其中大部分直接采用自嵌入式InnoDB
。 InnoDB
API 函数作为回调函数传递给InnoDB
memcached引擎。 InnoDB
API 函数直接访问InnoDB
表,大多数是 DML 操作,除了TRUNCATE TABLE
。
memcached命令通过InnoDB
memcached API 实现。以下表格概述了如何将memcached命令映射到 DML 或 DDL 操作。
表 17.27 memcached 命令及相关的 DML 或 DDL 操作
memcached 命令 | DML 或 DDL 操作 |
---|---|
get |
读取/获取命令 |
set |
一次搜索,然后是INSERT 或UPDATE (取决于键是否存在) |
add |
一次搜索,然后是INSERT 或UPDATE |
replace |
一次搜索,然后是UPDATE |
append |
一次搜索,然后是UPDATE (在UPDATE 之前将数据追加到结果中) |
prepend |
一次搜索,然后是UPDATE (在UPDATE 之前将数据前置到结果中) |
incr |
一次搜索,然后是UPDATE |
decr |
一次搜索,然后是UPDATE |
delete |
一次搜索,然后是DELETE |
flush_all |
TRUNCATE TABLE (DDL) |
memcached 命令 | DML 或 DDL 操作 |
InnoDB memcached 插件配置表
本节描述了daemon_memcached
插件使用的配置表。 cache_policies
表,config_options
表和containers
表由innodb_memcached_config.sql
配置脚本在innodb_memcache
数据库中创建。
mysql> USE innodb_memcache;
Database changed
mysql> SHOW TABLES;
+---------------------------+
| Tables_in_innodb_memcache |
+---------------------------+
| cache_policies |
| config_options |
| containers |
+---------------------------+
cache_policies 表
cache_policies
表定义了InnoDB
memcached
安装的缓存策略。您可以在单个缓存策略中为get
,set
,delete
和flush
操作指定单独的策略。所有操作的默认设置为innodb_only
。
-
innodb_only
: 使用InnoDB
作为数据存储。 -
cache_only
: 使用memcached引擎作为数据存储。 -
caching
: 同时使用InnoDB
和memcached引擎作为数据存储。在这种情况下,如果memcached在内存中找不到键,则会在InnoDB
表中搜索该值。 -
disable
: 禁用缓存。
表 17.28 cache_policies 列
列 | 描述 |
---|---|
policy_name |
缓存策略的名称。默认缓存策略名称为cache_policy 。 |
get_policy |
get 操作的缓存策略。有效值为innodb_only ,cache_only ,caching 或disabled 。默认设置为innodb_only 。 |
set_policy |
set 操作的缓存策略。有效值为innodb_only ,cache_only ,caching 或disabled 。默认设置为innodb_only 。 |
delete_policy |
删除操作的缓存策略。有效值为innodb_only 、cache_only 、caching 或disabled 。默认设置为innodb_only 。 |
flush_policy |
刷新操作的缓存策略。有效值为innodb_only 、cache_only 、caching 或disabled 。默认设置为innodb_only 。 |
config_options 表
config_options
表存储可以使用 SQL 在运行时更改的与memcached相关的设置。支持的配置选项是separator
和table_map_delimiter
。
表 17.29 config_options 列
列 | 描述 |
---|
| Name
| memcached相关配置选项的名称。config_options
表支持以下配置选项:
-
separator
:用于将长字符串的值分隔为单独的值的分隔符,当定义了多个value_columns
时。默认情况下,分隔符是|
字符。例如,如果您将col1, col2
定义为值列,并将|
定义为分隔符,则可以发出以下memcached命令将值分别插入到col1
和col2
中:set keyx 10 0 19 valuecolx|valuecoly
valuecol1x
存储在col1
中,valuecoly
存储在col2
中。 -
table_map_delimiter
:在使用@@
符号访问特定表中的键时,用于分隔模式名称和表名称的字符。例如,@@t1.some_key
和@@t2.some_key
具有相同的键值,但存储在不同的表中。
|
Value |
分配给与memcached相关的配置选项的值。 |
---|
containers 表
containers
表是三个配置表中最重要的一个。用于存储memcached值的每个InnoDB
表必须在containers
表中有一个条目。该条目提供了InnoDB
表列和容器表列之间的映射,这对于memcached
与InnoDB
表一起工作是必需的。
containers
表包含test.demo_test
表的默认条目,该表是由innodb_memcached_config.sql
配置脚本创建的。要使用daemon_memcached
插件与自己的InnoDB
表,必须在containers
表中创建一个条目。
表 17.30 containers 列
列 | 描述 |
---|---|
name |
分配给容器的名称。如果没有使用@@ 符号按名称请求InnoDB 表,则daemon_memcached 插件将使用具有containers.name 值为default 的InnoDB 表。如果没有这样的条目,则按name (升序)字母顺序排列的containers 表中的第一个条目确定默认的InnoDB 表。 |
db_schema |
包含InnoDB 表的数据库的名称。这是一个必填值。 |
db_table |
存储memcached值的InnoDB 表的名称。这是一个必填值。 |
key_columns |
包含memcached操作查找键值的InnoDB 表中的列。这是一个必填值。 |
value_columns |
存储memcached 数据的InnoDB 表列(一个或多个)。可以使用innodb_memcached.config_options 表中指定的分隔符字符指定多个列。默认情况下,分隔符是一个竖线字符(“ |
flags |
用作memcached标志(与主值一起存储和检索的用户定义的数值)的InnoDB 表列。如果memcached值映射到多个列,则标志值可以用作某些操作(如incr ,prepend )的列指定符,以便在指定列上执行操作。例如,如果你已将value_columns 映射到三个InnoDB 表列,并且只想要增量操作在一个列上执行,请使用flags 列指定该列。如果你不使用flags 列,请设置值为0 以指示未使用。 |
cas_column |
存储比较和交换(cas)值的InnoDB 表列。cas_column 值与memcached如何将请求哈希到不同服务器并在内存中缓存数据有关。由于InnoDB memcached插件与单个memcached守护程序紧密集成,并且内存缓存机制由 MySQL 和 InnoDB 缓冲池处理,因此很少需要此列。如果你不使用此列,请设置值为0 以指示未使用。 |
expire_time_column |
存储过期值的InnoDB 表列。expire_time_column 值与memcached如何将请求哈希到不同服务器并在内存中缓存数据有关。由于InnoDB memcached插件与单个memcached守护程序紧密集成,并且内存缓存机制由 MySQL 和 InnoDB 缓冲池处理,因此很少需要此列。如果你不使用此列,请设置值为0 以指示未使用。最大过期时间定义为INT_MAX32 或 2147483647 秒(约 68 年)。 |
unique_idx_name_on_key |
索引在关键列上的名称。它必须是一个唯一索引。它可以是主键或次要索引。最好使用InnoDB 表的主键。使用主键可以避免在使用次要索引时进行查找。你不能为memcached查找创建一个覆盖索引;如果你尝试在键和值列上定义一个复合次要索引,InnoDB 会返回错误。 |
容器表列约束
-
您必须为
db_schema
、db_name
、key_columns
、value_columns
和unique_idx_name_on_key
提供值。如果未使用,将flags
、cas_column
和expire_time_column
设置为0
。如果未这样做,可能会导致设置失败。 -
key_columns
: memcached键的最大限制为 250 个字符,由memcached强制执行。映射键必须是非空的CHAR
或VARCHAR
类型。 -
value_columns
: 必须映射到CHAR
、VARCHAR
或BLOB
列。没有长度限制,值可以为 NULL。 -
cas_column
:cas
值是 64 位整数。必须映射到至少 8 字节的BIGINT
。如果您不使用此列,请设置值为0
以指示未使用。 -
expiration_time_column
: 必须映射到至少 4 字节的INTEGER
。过期时间定义为 Unix 时间的 32 位整数(自 1970 年 1 月 1 日以来的秒数作为 32 位值),或从当前时间开始的秒数。对于后者,秒数不得超过 606024*30(30 天内的秒数)。如果客户端发送的数字较大,则服务器将其视为真实的 Unix 时间值,而不是从当前时间的偏移量。如果不使用此列,请设置值为0
以指示未使用。 -
flags
: 必须映射到至少 32 位的INTEGER
,可以为 NULL。如果您不使用此列,请设置值为0
以指示未使用。
在插件加载时执行预检查以强制执行列约束。如果发现不匹配,插件将不加载。
多值列映射
-
在插件初始化期间,当
InnoDB
memcached配置为containers
表中定义的信息时,将验证containers.value_columns
中定义的每个映射列与映射的InnoDB
表。如果映射了多个InnoDB
表列,则会检查以确保每个列存在且为正确类型。 -
在运行时,对于
memcached
插入操作,如果有比映射列数更多的分隔值,则仅取映射值的数量。例如,如果有六个映射列,并且提供了七个分隔值,则仅取前六个分隔值。第七个分隔值将被忽略。 -
如果分隔值少于映射的列数,未填充的列将被设置为 NULL。如果无法将未填充的列设置为 NULL,则插入操作将失败。
-
如果一个表的列数多于映射值,额外的列不会影响结果。
demo_test 示例表
innodb_memcached_config.sql
配置脚本在 test
数据库中创建了一个 demo_test
表,可用于在安装InnoDB
memcached 插件后立即验证安装。
innodb_memcached_config.sql
配置脚本还在 innodb_memcache.containers
表中为 demo_test
表创建了一个条目。
mysql> SELECT * FROM innodb_memcache.containers\G
*************************** 1\. row ***************************
name: aaa
db_schema: test
db_table: demo_test
key_columns: c1
value_columns: c2
flags: c3
cas_column: c4
expire_time_column: c5
unique_idx_name_on_key: PRIMARY
mysql> SELECT * FROM test.demo_test;
+----+------------------+------+------+------+
| c1 | c2 | c3 | c4 | c5 |
+----+------------------+------+------+------+
| AA | HELLO, HELLO | 8 | 0 | 0 |
+----+------------------+------+------+------+
17.20.9 解决 InnoDB memcached 插件问题
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-memcached-troubleshoot.html
本节描述了在使用InnoDB
memcached插件时可能遇到的问题。
-
如果在 MySQL 错误日志中遇到以下错误,则服务器可能无法启动:
设置打开文件数的限制失败。尝试以 root 用户身份运行或请求较小的 maxconns 值。
错误消息来自memcached守护程序。一个解决方案是提高操作系统打开文件数的限制。检查和增加打开文件限制的命令因操作系统而异。以下示例显示了 Linux 和 macOS 的命令:
# Linux $> ulimit -n 1024 $> ulimit -n 4096 $> ulimit -n 4096 # macOS $> ulimit -n 256 $> ulimit -n 4096 $> ulimit -n 4096
另一种解决方案是减少允许memcached守护程序的并发连接数。为此,在 MySQL 配置文件中的
daemon_memcached_option
配置参数中编码-c
memcached选项。-c
选项的默认值为 1024。[mysqld] ... loose-daemon_memcached_option='-c 64'
-
要解决memcached守护程序无法存储或检索
InnoDB
表数据的问题,请在 MySQL 配置文件的daemon_memcached_option
配置参数中编码-vvv
memcached选项。检查 MySQL 错误日志以获取与memcached操作相关的调试输出。[mysqld] ... loose-daemon_memcached_option='-vvv'
-
如果指定用于保存memcached值的列的数据类型错误,例如数字类型而不是字符串类型,则尝试存储键值对将失败,而不会显示特定的错误代码或消息。
-
如果
daemon_memcached
插件导致 MySQL 服务器启动问题,您可以在故障排除时通过在 MySQL 配置文件的[mysqld]
组下添加以下行来临时禁用daemon_memcached
插件:daemon_memcached=OFF
例如,如果在运行
innodb_memcached_config.sql
配置脚本设置必要的数据库和表之前运行INSTALL PLUGIN
语句,则服务器可能会意外退出并无法启动。如果在innodb_memcache.containers
表中错误配置条目,服务器也可能无法启动。要卸载 MySQL 实例的memcached插件,请发出以下语句:
mysql> UNINSTALL PLUGIN daemon_memcached;
-
如果在同一台机器上运行多个 MySQL 实例,并且每个实例都启用了
daemon_memcached
插件,请使用daemon_memcached_option
配置参数为每个daemon_memcached
插件指定一个独特的memcached端口。 -
如果一个 SQL 语句无法找到
InnoDB
表或在表中找不到数据,但memcached API 调用检索到了预期的数据,那么可能是在innodb_memcache.containers
表中缺少了InnoDB
表的条目,或者您可能没有通过使用@@*
table_id*
标记发出get
或set
请求来切换到正确的InnoDB
表。如果您在之后没有重新启动 MySQL 服务器的情况下更改了innodb_memcache.containers
表中的现有条目,也可能会出现这个问题。自由形式的存储机制足够灵活,即使守护程序正在使用将值存储在单列中的test.demo_test
表,您对存储或检索多列值(如col1|col2|col3
)的请求可能仍然有效。 -
在为
daemon_memcached
插件定义自己的InnoDB
表时,如果表中的列被定义为NOT NULL
,请确保在将表的记录插入innodb_memcache.containers
表时为NOT NULL
列提供值。如果innodb_memcache.containers
记录的INSERT
语句包含的分隔值少于映射列的数量,未填充的列将被设置为NULL
。尝试将NULL
值插入NOT NULL
列会导致INSERT
失败,这可能只有在重新初始化daemon_memcached
插件以应用对innodb_memcache.containers
表的更改后才会显现。 -
如果
innodb_memcached.containers
表的cas_column
和expire_time_column
字段设置为NULL
,则在尝试加载memcached插件时会返回以下错误:InnoDB_Memcached: column 6 in the entry for config table 'containers' in database 'innodb_memcache' has an invalid NULL value.
memcached插件拒绝在
cas_column
和expire_time_column
列中使用NULL
。当这些列未使用时,将这些列的值设置为0
。 -
随着memcached键和值的长度增加,您可能会遇到大小和长度限制。
-
当键超过 250 字节时,memcached操作会返回错误。这是memcached中当前的固定限制。
-
如果值的大小超过 768 字节、3072 字节或半个
innodb_page_size
值,可能会遇到InnoDB
表限制。这些限制主要适用于如果您打算在值列上创建索引以使用 SQL 运行生成报表的查询时。有关详细信息,请参见第 17.22 节,“InnoDB 限制”。 -
键-值组合的最大大小为 1 MB。
-
-
如果在不同版本的 MySQL 服务器之间共享配置文件,并且使用
daemon_memcached
插件的最新配置选项可能会导致在旧的 MySQL 版本上启动错误。为避免兼容性问题,请在选项名称前使用loose
前缀。例如,使用loose-daemon_memcached_option='-c 64'
而不是daemon_memcached_option='-c 64'
。 -
没有限制或检查来验证字符集设置。memcached以字节形式存储和检索键和值,因此不受字符集的影响。但是,您必须确保memcached客户端和 MySQL 表使用相同的字符集。
-
memcached连接被阻止访问包含索引虚拟列的表。访问索引虚拟列需要回调到服务器,但memcached连接无法访问服务器代码。
17.21 InnoDB 故障排除
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting.html
17.21.1 故障排除 InnoDB I/O 问题
17.21.2 故障排除恢复失败
17.21.3 强制 InnoDB 恢复
17.21.4 故障排除 InnoDB 数据字典操作
17.21.5 InnoDB 错误处理
以下一般准则适用于故障排除 InnoDB
问题:
-
当操作失败或怀疑存在 bug 时,请查看 MySQL 服务器错误日志(参见 7.4.2 “错误日志”)。服务器错误消息参考 提供了一些常见的
InnoDB
特定错误的故障排除信息。 -
如果故障与死锁有关,请启用
innodb_print_all_deadlocks
选项运行,以便将每个死锁的详细信息打印到 MySQL 服务器错误日志中。有关死锁的信息,请参见 17.7.5 “InnoDB 中的死锁”。 -
如果问题与
InnoDB
数据字典有关,请参见 17.21.4 “故障排除 InnoDB 数据字典操作”。 -
在故障排除时,通常最好从命令提示符下运行 MySQL 服务器,而不是通过 mysqld_safe 或作为 Windows 服务运行。然后您可以看到 mysqld 打印到控制台的内容,从而更好地了解发生了什么。在 Windows 上,使用
--console
选项启动 mysqld,将输出定向到控制台窗口。 -
启用
InnoDB
Monitors 以获取有关问题的信息(参见 17.17 “InnoDB Monitors”)。如果问题与性能有关,或者服务器似乎挂起,您应该启用标准 Monitor 以打印有关InnoDB
内部状态的信息。如果问题与锁有关,请启用 Lock Monitor。如果问题与表创建、表空间或数据字典操作有关,请参考 InnoDB 信息模式系统表 来检查InnoDB
内部数据字典的内容。InnoDB
在以下情况下临时启用标准InnoDB
Monitor 输出:-
一个长时间的信号量等待
-
InnoDB
在缓冲池中找不到空闲块。 -
缓冲池超过
67%
被锁堆或自适应哈希索引占用。
-
-
如果你怀疑某个表损坏,运行
CHECK TABLE
命令检查该表。
17.21.1 解决 InnoDB I/O 问题
原文:
dev.mysql.com/doc/refman/8.0/en/error-creating-innodb.html
处理InnoDB
I/O 问题的故障排除步骤取决于问题发生的时间:MySQL 服务器启动期间,或者在正常操作期间,当 DML 或 DDL 语句由于文件系统级别的问题而失败时。
初始化问题
如果InnoDB
在尝试初始化其表空间或日志文件时出现问题,请删除InnoDB
创建的所有文件:所有ibdata
文件和所有重做日志文件(MySQL 8.0.30 及更高版本中的#ib_redo*
N*
文件或早期版本中的ib_logfile
文件)。如果您创建了任何InnoDB
表,还要从 MySQL 数据库目录中删除任何.ibd
文件。然后尝试重新初始化InnoDB
。为了进行最简单的故障排除,请从命令提示符启动 MySQL 服务器,以便查看发生了什么。
运行时问题
如果InnoDB
在文件操作期间打印操作系统错误,通常问题有以下解决方案之一:
-
确保
InnoDB
数据文件目录和InnoDB
日志目录存在。 -
确保mysqld有权限在这些目录中创建文件。
-
确保mysqld可以读取正确的
my.cnf
或my.ini
选项文件,以便它以您指定的选项启动。 -
确保磁盘未满,并且未超出任何磁盘配额。
-
确保您为子目录和数据文件指定的名称不冲突。
-
仔细检查
innodb_data_home_dir
和innodb_data_file_path
值的语法。特别是,在innodb_data_file_path
选项中的任何MAX
值都是一个硬限制,超过该限制会导致致命错误。
17.21.2 故障恢复失败的故障排除
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-recovery.html
从 MySQL 8.0.26 开始,在重做日志恢复完成并且数据字典动态元数据(srv_dict_metadata
)转移到数据字典表(dict_table_t
)对象之前,不允许进行检查点和推进检查点 LSN。如果在恢复期间或恢复后(但在数据字典动态元数据转移到数据字典表对象之前)重做日志空间不足,可能需要进行innodb_force_recovery
重启,至少从SRV_FORCE_NO_IBUF_MERGE
设置开始,或者在失败的情况下,从SRV_FORCE_NO_LOG_REDO
设置开始。如果在这种情况下innodb_force_recovery
重启失败,可能需要从备份中恢复。(Bug #32200595)
17.21.3 强制 InnoDB 恢复
原文:
dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html
为了调查数据库页面损坏,您可以使用 SELECT ... INTO OUTFILE
从数据库中导出表。通常,以这种方式获得的大部分数据是完整的。严重的损坏可能会导致 SELECT * FROM *
tbl_name*
语句或 InnoDB
后台操作意外退出或断言,甚至导致 InnoDB
回滚恢复崩溃。在这种情况下,您可以使用 innodb_force_recovery
选项来强制 InnoDB
存储引擎启动,同时阻止后台操作运行,以便您可以导出表。例如,您可以在重新启动服务器之前将以下行添加到您的选项文件的 [mysqld]
部分中:
[mysqld]
innodb_force_recovery = 1
有关使用选项文件的信息,请参见 Section 6.2.2.2, “Using Option Files”。
警告
仅在紧急情况下将 innodb_force_recovery
设置为大于 0 的值,以便您可以启动 InnoDB
并导出表。在这样做之前,请确保您有数据库的备份副本,以防需要重新创建它。值为 4 或更大可能会永久损坏数据文件。仅在成功在数据库的单独物理副本上测试设置后,才在生产服务器实例上使用大于 4 的 innodb_force_recovery
设置。在强制 InnoDB
恢复时,您应始终从 innodb_force_recovery=1
开始,并根据需要逐渐增加值。
innodb_force_recovery
默认为 0(正常启动,无需强制恢复)。innodb_force_recovery
允许的非零值为 1 到 6。较大的值包含较小值的功能。例如,值为 3 包含值为 1 和 2 的所有功能。
如果您能够使用值为 3 或更低的 innodb_force_recovery
导出表,那么您相对安全,只有一些损坏的单个页面上的数据丢失。值为 4 或更大被认为是危险的,因为数据文件可能会永久损坏。值为 6 被认为是极端的,因为数据库页面处于过时状态,这反过来可能会在 B 树 和其他数据库结构中引入更多损坏。
作为安全措施,当innodb_force_recovery
大于 0 时,InnoDB
会阻止INSERT
、UPDATE
或DELETE
操作。设置为 4 或更高的innodb_force_recovery
值会将InnoDB
置于只读模式。
-
1
(SRV_FORCE_IGNORE_CORRUPT
)让服务器即使检测到损坏的页面也能继续运行。尝试使
SELECT * FROM * tbl_name *
跳过损坏的索引记录和页面,有助于导出表格。 -
2
(SRV_FORCE_NO_BACKGROUND
)阻止主线程和任何清理线程运行。如果在清理操作期间发生意外退出,此恢复值将阻止它。
-
3
(SRV_FORCE_NO_TRX_UNDO
)在崩溃恢复后不运行事务回滚。
-
4
(SRV_FORCE_NO_IBUF_MERGE
)阻止插入缓冲区合并操作。如果这些操作可能导致崩溃,则不执行。不计算表的统计信息。这个值可能会永久损坏数据文件。使用此值后,准备好删除并重新创建所有辅助索引。将
InnoDB
设置为只读。 -
5
(SRV_FORCE_NO_UNDO_LOG_SCAN
)在启动数据库时不查看撤销日志:
InnoDB
将即使是不完整的事务也视为已提交。这个值可能会永久损坏数据文件。将InnoDB
设置为只读。 -
6
(SRV_FORCE_NO_LOG_REDO
)在恢复过程中不执行重做日志的前进。这个值可能会永久损坏数据文件。将数据库页面留在过时状态,这可能会导致 B 树和其他数据库结构出现更多损坏。将
InnoDB
设置为只读。
您可以从表中SELECT
以导出它们。当innodb_force_recovery
值为 3 或更低时,可以DROP
或CREATE
表。当innodb_force_recovery
值大于 3 时,也支持DROP TABLE
。当innodb_force_recovery
值大于 4 时,不允许DROP TABLE
。
如果您知道某个表在回滚时导致意外退出,您可以将其删除。如果遇到由于失败的大规模导入或ALTER TABLE
导致的无限回滚,您可以终止mysqld进程,并将innodb_force_recovery
设置为3
,以在没有回滚的情况下启动数据库,然后DROP
掉导致无限回滚的表。
如果表数据中的损坏阻止您转储整个表内容,带有ORDER BY *primary_key* DESC
子句的查询可能能够转储受损部分之后的表部分。
如果需要较高的innodb_force_recovery
值才能启动InnoDB
,可能存在损坏的数据结构,可能导致复杂查询(包含WHERE
、ORDER BY
或其他子句的查询)失败。在这种情况下,您可能只能运行基本的SELECT * FROM t
查询。
17.21.4 InnoDB 数据字典操作故障排除
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-datadict.html
表定义信息存储在 InnoDB 数据字典中。如果移动数据文件,字典数据可能变得不一致。
如果数据字典损坏或一致性问题阻止您启动InnoDB
,请参阅第 17.21.3 节,“强制 InnoDB 恢复”以获取有关手动恢复的信息。
无法打开数据文件
启用innodb_file_per_table
(默认情况下),如果缺少 file-per-table 表空间文件(.ibd
文件),则可能在启动时出现以下消息:
[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Cannot open datafile for read-only: './test/t1.ibd' OS error: 71
[Warning] InnoDB: Ignoring tablespace `test/t1` because it could not be opened.
要解决这些消息,请发出DROP TABLE
语句,以从数据字典中删除有关缺失表的数据。
恢复孤立的 file-per-table ibd 文件
该过程描述了如何将孤立的 file-per-table.ibd
文件恢复到另一个 MySQL 实例。如果系统表空间丢失或无法恢复,并且您想要在新的 MySQL 实例上恢复.ibd
文件备份,则可以使用此过程。
该过程不支持 general tablespace.ibd
文件。
该过程假定您只有.ibd
文件备份,您正在恢复到最初创建孤立的.ibd
文件的 MySQL 版本,并且.ibd
文件备份是干净的。有关创建干净备份的信息,请参阅第 17.6.1.4 节,“移动或复制 InnoDB 表”。
第 17.6.1.3 节,“导入 InnoDB 表”中概述的表导入限制适用于此过程。
-
在新的 MySQL 实例中,在同名数据库中重新创建表。
mysql> CREATE DATABASE sakila; mysql> USE sakila; mysql> CREATE TABLE actor ( actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, first_name VARCHAR(45) NOT NULL, last_name VARCHAR(45) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (actor_id), KEY idx_actor_last_name (last_name) )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
丢弃新创建表的表空间。
mysql> ALTER TABLE sakila.actor DISCARD TABLESPACE;
-
将孤立的
.ibd
文件从备份目录复制到新的数据库目录。$> cp /backup_directory/actor.ibd *path/to/mysql-5.7/data*/sakila/
-
确保
.ibd
文件具有必要的文件权限。 -
导入孤立的
.ibd
文件。会发出警告,指示InnoDB
正在尝试在没有模式验证的情况下导入文件。mysql> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS; Query OK, 0 rows affected, 1 warning (0.15 sec) Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './sakila/actor.cfg', will attempt to import without schema verification
-
查询表以验证
.ibd
文件是否成功恢复。mysql> SELECT COUNT(*) FROM sakila.actor; +----------+ | count(*) | +----------+ | 200 | +----------+
17.21.5 InnoDB 错误处理
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-error-handling.html
以下项目描述了InnoDB
如何执行错误处理。InnoDB
有时只回滚失败的语句,有时会回滚整个事务。
-
如果在表空间中耗尽文件空间,则会发生 MySQL
Table is full
错误,并且InnoDB
会回滚 SQL 语句。 -
事务死锁会导致
InnoDB
回滚整个事务。发生这种情况时,请重试整个事务。锁等待超时会导致
InnoDB
回滚当前语句(等待锁并遇到超时的语句)。要使整个事务回滚,请启动服务器时启用--innodb-rollback-on-timeout
。如果使用默认行为,请重试语句,或者如果启用了--innodb-rollback-on-timeout
,则重试整个事务。在繁忙服务器上,死锁和锁等待超时是正常的,应用程序需要意识到它们可能发生,并通过重试来处理。通过在事务期间对数据进行第一次更改和提交之间尽可能少地进行工作,可以减少发生这些情况的可能性,从而锁定的时间最短,影响的行数最少。有时将工作分割到不同的事务中可能是实用和有帮助的。
-
如果发生重复键错误,则回滚 SQL 语句,如果在语句中未指定
IGNORE
选项。 -
行过长错误
会回滚 SQL 语句。 -
其他错误大多由 MySQL 代码层(在
InnoDB
存储引擎层之上)检测到,并回滚相应的 SQL 语句。在回滚单个 SQL 语句时不会释放锁。
在隐式回滚期间,以及在执行显式ROLLBACK
SQL 语句期间,SHOW PROCESSLIST
在相关连接的State
列中显示Rolling back
。
17.22 InnoDB 限制
本节描述了 InnoDB
表、索引、表空间以及 InnoDB
存储引擎的其他方面的限制。
-
一张表最多可以包含 1017 列。虚拟生成列也包括在此限制内。
-
一张表最多可以包含 64 个次要索引。
-
对于使用
DYNAMIC
或COMPRESSED
行格式的InnoDB
表,索引键前缀长度限制为 3072 字节。对于使用
REDUNDANT
或COMPACT
行格式的InnoDB
表,索引键前缀长度限制为 767 字节。例如,假设在TEXT
或VARCHAR
列上使用了超过 191 个字符的 列前缀 索引,在utf8mb4
字符集和每个字符最大 4 个字节的情况下,可能会达到这个限制。尝试使用超过限制的索引键前缀长度将返回错误。
如果通过在创建 MySQL 实例时指定
innodb_page_size
选项将InnoDB
页大小 降低为 8KB 或 4KB,那么基于 16KB 页大小的 3072 字节限制,索引键的最大长度将按比例降低。也就是说,当页大小为 8KB 时,最大索引键长度为 1536 字节,当页大小为 4KB 时,最大索引键长度为 768 字节。适用于索引键前缀的限制也适用于完整列索引键。
-
最多允许为多列索引设置 16 列。超过限制将返回错误。
ERROR 1070 (42000): Too many key parts specified; max 16 parts allowed
-
行的最大大小,不包括存储在页外的任何可变长度列,对于 4KB、8KB、16KB 和 32KB 的页大小略小于半页。例如,默认的
innodb_page_size
为 16KB 时,最大行大小约为 8000 字节。然而,对于 64KB 的InnoDB
页大小,最大行大小约为 16000 字节。LONGBLOB
和LONGTEXT
列必须小于 4GB,包括BLOB
和TEXT
列在内的总行大小必须小于 4GB。如果一行长度小于半页,所有内容都存储在页面内。如果超过半页,变长列将选择外部离页存储,直到行适合半页为止,如第 17.11.2 节,“文件空间管理”中所述。
-
尽管
InnoDB
内部支持大于 65535 字节的行大小,但 MySQL 本身对所有列的组合大小施加了 65535 的行大小限制。请参见第 10.4.7 节,“表列数和行大小限制”。 -
在一些较旧的操作系统上,文件大小必须小于 2GB。这不是
InnoDB
的限制。如果您需要一个大的系统表空间,请使用多个较小的数据文件进行配置,而不是一个大的数据文件,或者将表数据分布在每个表一个文件和通用表空间数据文件中。 -
InnoDB
日志文件的组合最大大小为 512GB。 -
最小表空间大小略大于 10MB。最大表空间大小取决于
InnoDB
页面大小。表 17.31 InnoDB 最大表空间大小
InnoDB 页面大小 最大表空间大小 4KB 16TB 8KB 32TB 16KB 64TB 32KB 128TB 64KB 256TB 最大表空间大小也是表的最大大小。
-
一个
InnoDB
实例支持最多 2³²(4294967296)个表空间,其中少数表空间保留用于撤销和临时表。 -
共享表空间支持最多 2³²(4294967296)个表。
-
表空间文件的路径,包括文件名,在 Windows 上不能超过
MAX_PATH
限制。在 Windows 10 之前,MAX_PATH
限制为 260 个字符。从 Windows 10,版本 1607 开始,MAX_PATH
限制已从常见的 Win32 文件和目录函数中移除,但您必须启用新的行为。 -
有关并发读写事务相关的限制,请参见第 17.6.6 节,“撤销日志”。
17.23 InnoDB 限制和限制
原文:
dev.mysql.com/doc/refman/8.0/en/innodb-restrictions-limitations.html
本节描述了 InnoDB
存储引擎的限制和限制。
-
不能创建具有与内部
InnoDB
列名匹配的列名的表(包括DB_ROW_ID
、DB_TRX_ID
和DB_ROLL_PTR
)。此限制适用于任何大小写形式中的名称使用。mysql> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB; ERROR 1166 (42000): Incorrect column name 'db_row_id'
-
SHOW TABLE STATUS
对于InnoDB
表不提供准确的统计信息,除了表保留的物理大小。行计数仅是 SQL 优化中使用的粗略估计。 -
InnoDB
不会保留表中行的内部计数,因为并发事务可能在同一时间“看到”不同数量的行。因此,SELECT COUNT(*)
语句仅计算当前事务可见的行数。有关
InnoDB
如何处理SELECT COUNT(*)
语句的信息,请参阅 第 14.19.1 节,“聚合函数描述” 中的COUNT()
描述。 -
ROW_FORMAT=COMPRESSED
不支持大于 16KB 的页面大小。 -
使用特定
InnoDB
页面大小(innodb_page_size
)的 MySQL 实例不能使用来自使用不同页面大小的实例的数据文件或日志文件。 -
有关使用 可传输表空间 功能导入表的限制,请参见 表导入限制。
-
有关在线 DDL 的限制,请参见 第 17.12.8 节,“在线 DDL 限制”。
-
有关一般表空间的限制,请参见 一般表空间限制。
-
有关数据静态加密的限制,请参见 加密限制。
第十八章 备选存储引擎
目录
18.1 设置存储引擎
18.2 MyISAM 存储引擎
18.2.1 MyISAM 启动选项
18.2.2 键所需的空间
18.2.3 MyISAM 表存储格式
18.2.4 MyISAM 表问题
18.3 MEMORY 存储引擎
18.4 CSV 存储引擎
18.4.1 修复和检查 CSV 表
18.4.2 CSV 限制
18.5 ARCHIVE 存储引擎
18.6 BLACKHOLE 存储引擎
18.7 MERGE 存储引擎
18.7.1 MERGE 表优缺点
18.7.2 MERGE 表问题
18.8 FEDERATED 存储引擎
18.8.1 FEDERATED 存储引擎概述
18.8.2 如何创建 FEDERATED 表
18.8.3 FEDERATED 存储引擎注意事项和提示
18.8.4 FEDERATED 存储引擎资源
18.9 EXAMPLE 存储引擎
18.10 其他存储引擎
18.11 MySQL 存储引擎架构概述
18.11.1 可插拔存储引擎架构
18.11.2 通用数据库服务器层
存储引擎是 MySQL 组件,用于处理不同表类型的 SQL 操作。InnoDB
是默认和最通用的存储引擎,Oracle 建议除了专用用例外,都使用它来创建表。(在 MySQL 8.0 中,CREATE TABLE
语句默认创建 InnoDB
表。)
MySQL 服务器使用可插拔存储引擎架构,允许存储引擎在运行中加载和卸载。
要确定服务器支持哪些存储引擎,请使用 SHOW ENGINES
语句。Support
列中的值指示引擎是否可用。YES
、NO
或 DEFAULT
的值表示引擎可用、不可用或可用且当前设置为默认存储引擎。
mysql> SHOW ENGINES\G
*************************** 1\. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2\. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 3\. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4\. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 5\. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
...
本章涵盖了特定用途的 MySQL 存储引擎的使用案例。它不涵盖默认的 InnoDB
存储引擎或 NDB
存储引擎,这些在 Chapter 17, The InnoDB Storage Engine 和 Chapter 25, MySQL NDB Cluster 8.0 中有介绍。对于高级用户,它还包含了可插拔存储引擎架构的描述(请参见 Section 18.11, “Overview of MySQL Storage Engine Architecture”)。
有关商业 MySQL Server 二进制版本提供的功能信息,请访问 MySQL 网站上的MySQL Editions。可用的存储引擎可能取决于您使用的 MySQL 版本。
关于 MySQL 存储引擎常见问题的答案,请参见 Section A.2, “MySQL 8.0 FAQ: Storage Engines”。
MySQL 8.0 支持的存储引擎
-
InnoDB
:MySQL 8.0 中的默认存储引擎。InnoDB
是 MySQL 的事务安全(ACID 兼容)存储引擎,具有提交、回滚和崩溃恢复功能,以保护用户数据。InnoDB
行级锁定(不升级为更粗粒度的锁)和 Oracle 风格的一致性非锁定读取增加了多用户并发性和性能。InnoDB
将用户数据存储在聚集索引中,以减少基于主键的常见查询的 I/O。为了保持数据完整性,InnoDB
还支持FOREIGN KEY
外键完整性约束。有关InnoDB
的更多信息,请参见 Chapter 17, The InnoDB Storage Engine。 -
MyISAM
:这些表占用空间小。表级锁定 限制了读/写工作负载的性能,因此通常用于 Web 和数据仓库配置中的只读或读多写少的工作负载。 -
Memory
:将所有数据存储在 RAM 中,用于快速访问需要快速查找非关键数据的环境。这个引擎以前被称为HEAP
引擎。它的使用案例正在减少;InnoDB
通过其缓冲池内存区提供了一种通用且耐用的方式来将大部分或全部数据保存在内存中,而NDBCLUSTER
为庞大的分布式数据集提供了快速的键值查找。 -
CSV
:它的表实际上是带有逗号分隔值的文本文件。CSV 表允许你以 CSV 格式导入或导出数据,与读写相同格式的脚本和应用程序交换数据。因为 CSV 表没有索引,通常在正常操作期间将数据保存在InnoDB
表中,仅在导入或导出阶段使用 CSV 表。 -
归档
:这些紧凑的、无索引的表用于存储和检索大量很少被引用的历史、归档或安全审计信息。 -
黑洞
:黑洞存储引擎接受但不存储数据,类似于 Unix 的/dev/null
设备。查询总是返回一个空集。这些表可以在复制配置中使用,其中 DML 语句被发送到副本服务器,但源服务器不保留自己的数据副本。 -
NDB
(也称为NDBCLUSTER
):这个集群数据库引擎特别适用于需要最高可用性和可用性的应用程序。 -
合并
:使 MySQL DBA 或开发人员可以逻辑地将一系列相同的MyISAM
表分组,并将它们引用为一个对象。适用于数据仓库等 VLDB 环境。 -
联合
:提供了将不同的 MySQL 服务器链接起来,从许多物理服务器创建一个逻辑数据库的能力。非常适合分布式或数据仓库环境。 -
示例
:这个引擎在 MySQL 源代码中作为一个示例,展示了如何开始编写新的存储引擎。主要是为开发人员感兴趣。这个存储引擎是一个“存根”,什么也不做。你可以用这个引擎创建表,但不能在其中存储或检索数据。
你不必限制整个服务器或模式使用相同的存储引擎。你可以为任何表指定存储引擎。例如,一个应用程序可能主要使用InnoDB
表,其中一个CSV
表用于将数据导出到电子表格,以及一些MEMORY
表用于临时工作空间。
选择存储引擎
MySQL 提供的各种存储引擎是针对不同用例设计的。以下表格提供了一些 MySQL 提供的存储引擎的概述,表格后面跟着澄清说明。
表 18.1 存储引擎特性摘要
特性 | MyISAM | Memory | InnoDB | Archive | NDB |
---|---|---|---|---|---|
B-tree 索引 | 是 | 是 | 是 | 否 | 否 |
备份/时间点恢复(注 1) | 是 | 是 | 是 | 是 | 是 |
集群数据库支持 | 否 | 否 | 否 | 否 | 是 |
聚集索引 | 否 | 否 | 是 | 否 | 否 |
压缩数据 | 是(注 2) | 否 | 是 | 是 | 否 |
数据缓存 | 否 | 不适用 | 是 | 否 | 是 |
加密数据 | 是(注 3) | 是(注 3) | 是(注 4) | 是(注 3) | 是(注 5) |
外键支持 | 否 | 否 | 是 | 否 | 是 |
全文搜索索引 | 是 | 否 | 是(注 6) | 否 | 否 |
地理空间数据类型支持 | 是 | 否 | 是 | 是 | 是 |
地理空间索引支持 | 是 | 否 | 是(注 7) | 否 | 否 |
哈希索引 | 否 | 是 | 否(注 8) | 否 | 是 |
索引缓存 | 是 | 不适用 | 是 | 否 | 是 |
锁定粒度 | 表 | 表 | 行 | 行 | 行 |
MVCC | 否 | 否 | 是 | 否 | 否 |
复制支持(注 1) | 是 | 有限(注 9) | 是 | 是 | 是 |
存储限制 | 256TB | RAM | 64TB | 无 | 384EB |
T 树索引 | 否 | 否 | 否 | 否 | 是 |
事务 | 否 | 否 | 是 | 否 | 是 |
更新数据字典的统计信息 | 是 | 是 | 是 | 是 | 是 |
特性 | MyISAM | Memory | InnoDB | Archive | NDB |
注:
1. 在服务器端实现,而不是在存储引擎中。
2. 仅当使用压缩行格式时,支持压缩的 MyISAM 表。使用压缩行格式的 MyISAM 表是只读的。
3. 通过加密函数在服务器端实现。
4. 通过加密函数在服务器端实现;在 MySQL 5.7 及更高版本中,支持数据静态加密。
5. 通过加密函数在服务器端实现;NDB 8.0.22 起支持加密的 NDB 备份;NDB 8.0.29 及更高版本支持透明的 NDB 文件系统加密。
6. MySQL 5.6 及更高版本支持全文索引。
7. MySQL 5.7 及更高版本支持地理空间索引。
8. InnoDB 在内部利用哈希索引来实现其自适应哈希索引功能。
9. 请参见本节后面的讨论。
18.1 设置存储引擎
原文:
dev.mysql.com/doc/refman/8.0/en/storage-engine-setting.html
当您创建新表时,可以通过在CREATE TABLE
语句中添加ENGINE
表选项来指定要使用的存储引擎:
-- ENGINE=INNODB not needed unless you have set a different
-- default storage engine.
CREATE TABLE t1 (i INT) ENGINE = INNODB;
-- Simple table definitions can be switched from one to another.
CREATE TABLE t2 (i INT) ENGINE = CSV;
CREATE TABLE t3 (i INT) ENGINE = MEMORY;
当您省略ENGINE
选项时,将使用默认存储引擎。在 MySQL 8.0 中,默认引擎是InnoDB
。您可以通过使用--default-storage-engine
服务器启动选项或通过在my.cnf
配置文件中设置default-storage-engine
选项来指定默认引擎。
您可以通过设置default_storage_engine
变量为当前会话设置默认存储引擎:
SET default_storage_engine=NDBCLUSTER;
使用CREATE TEMPORARY TABLE
创建的TEMPORARY
表的存储引擎可以通过在启动时或运行时设置default_tmp_storage_engine
来单独设置,与永久表的引擎不同。
要将表从一种存储引擎转换为另一种,使用指示新引擎的ALTER TABLE
语句:
ALTER TABLE t ENGINE = InnoDB;
参见第 15.1.20 节,“CREATE TABLE Statement”和第 15.1.9 节,“ALTER TABLE Statement”。
如果您尝试使用未编译或已编译但已停用的存储引擎,MySQL 会使用默认存储引擎创建表。例如,在复制设置中,也许您的源服务器使用InnoDB
表以获得最大安全性,但副本服务器使用其他存储引擎以换取速度而牺牲耐久性或并发性。
默认情况下,当CREATE TABLE
或ALTER TABLE
无法使用默认存储引擎时会生成警告。为了防止混淆和意外行为,如果所需引擎不可用,请启用NO_ENGINE_SUBSTITUTION
SQL 模式。如果所需引擎不可用,此设置会产生错误而不是警告,并且表不会被创建或更改。参见第 7.1.11 节,“服务器 SQL 模式”。
MySQL 可能会根据存储引擎的不同,将表的索引和数据存储在一个或多个其他文件中。表和列的定义存储在 MySQL 数据字典中。各个存储引擎会为其管理的表创建所需的任何额外文件。如果表名包含特殊字符,则表文件的名称会包含这些字符的编码版本,如 Section 11.2.4,“标识符映射到文件名”中所述。
18.2 MyISAM 存储引擎
原文:
dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html
18.2.1 MyISAM 启动选项
18.2.2 键所需的空间
18.2.3 MyISAM 表存储格式
18.2.4 MyISAM 表问题
MyISAM
基于旧的(不再可用)ISAM
存储引擎,但具有许多有用的扩展。
表 18.2 MyISAM 存储引擎特性
功能 | 支持 |
---|---|
B 树索引 | 是 |
备份/时间点恢复(在服务器中实现,而不是在存储引擎中。) | 是 |
集群数据库支持 | 否 |
聚集索引 | 否 |
压缩数据 | 是(仅在使用压缩行格式时支持压缩的 MyISAM 表。使用压缩行格式和 MyISAM 的表是只读的。) |
数据缓存 | 否 |
加密数据 | 是(通过加密函数在服务器中实现。) |
外键支持 | 否 |
全文搜索索引 | 是 |
地理空间数据类型支持 | 是 |
地理空间索引支持 | 是 |
哈希索引 | 否 |
索引缓存 | 是 |
锁定粒度 | 表 |
MVCC | 否 |
复制支持(在服务器中实现,而不是在存储引擎中。) | 是 |
存储限制 | 256TB |
T 树索引 | 否 |
事务 | 否 |
更新数据字典的统计信息 | 是 |
功能 | 支持 |
每个MyISAM
表在磁盘上以两个文件存储。这些文件的名称以表名开头,并具有指示文件类型的扩展名。数据文件具有.MYD
(MYData
)扩展名。索引文件具有.MYI
(MYIndex
)扩展名。表定义存储在 MySQL 数据字典中。
要明确指定要使用MyISAM
表,可以使用ENGINE
表选项指示:
CREATE TABLE t (i INT) ENGINE = MYISAM;
在 MySQL 8.0 中,通常需要使用ENGINE
来指定MyISAM
存储引擎,因为InnoDB
是默认引擎。
您可以使用mysqlcheck客户端或myisamchk实用程序检查或修复MyISAM
表。您还可以使用myisampack压缩MyISAM
表,以占用更少的空间。请参阅 Section 6.5.3, “mysqlcheck — A Table Maintenance Program”,Section 6.6.4, “myisamchk — MyISAM Table-Maintenance Utility”和 Section 6.6.6, “myisampack — Generate Compressed, Read-Only MyISAM Tables”。
在 MySQL 8.0 中,MyISAM
存储引擎不提供分区支持。在以前的 MySQL 版本中创建的分区MyISAM
表无法在 MySQL 8.0 中使用。有关更多信息,请参见第 26.6.2 节,“与存储引擎相关的分区限制”。有关升级这些表以便在 MySQL 8.0 中使用的帮助,请参见第 3.5 节,“MySQL 8.0 中的更改”。
MyISAM
表具有以下特点:
-
所有数据值都以低字节优先存储。这使得数据与机器和操作系统无关。对于二进制可移植性的唯一要求是机器使用二进制补码有符号整数和 IEEE 浮点格式。这些要求在主流机器中被广泛使用。二进制兼容性可能不适用于有时具有特殊处理器的嵌入式系统。
以低字节优先存储数据不会带来显著的速度惩罚;表行中的字节通常是不对齐的,读取不对齐字节按顺序比按相反顺序需要更少的处理。此外,服务器中提取列值的代码与其他代码相比并不是时间关键。
-
所有数值键值都以高字节优先存储,以便更好地压缩索引。
-
支持大文件(最多 63 位文件长度)的文件系统和操作系统。
-
MyISAM
表中最多有(2³²)²(1.844E+19)行。 -
每个
MyISAM
表的最大索引数为 64。每个索引的最大列数为 16。
-
最大键长度为 1000 字节。这可以通过更改源代码并重新编译来改变。对于长度超过 250 字节的键,使用比默认的 1024 字节更大的键块大小。
-
当按排序顺序插入行时(例如使用
AUTO_INCREMENT
列时),索引树会分裂,使高节点仅包含一个键。这提高了索引树的空间利用率。 -
每个表支持一个
AUTO_INCREMENT
列的内部处理。MyISAM
自动更新此列的INSERT
和UPDATE
操作。这使得AUTO_INCREMENT
列更快(至少快 10%)。在删除后,顺序顶部的值不会被重用。(当AUTO_INCREMENT
列被定义为多列索引的最后一列时,从顺序顶部删除的值会被重用。)AUTO_INCREMENT
值可以通过ALTER TABLE
或myisamchk重置。 -
在混合删除、更新和插入时,动态大小的行碎片化较少。这是通过自动组合相邻的已删除块和在下一个块被删除时扩展块来完成的。
-
MyISAM
支持并发插入:如果表在数据文件中间没有空闲块,您可以在其他线程从表中读取数据的同时向其插入新行。空闲块可能是由于删除行或更新动态长度行而导致的,其数据超过当前内容。当所有空闲块都被使用完(填满)时,未来的插入操作再次变得并发。参见 Section 10.11.3, “Concurrent Inserts”。 -
将数据文件和索引文件放在不同的目录中,放在不同的物理设备上,可以通过
DATA DIRECTORY
和INDEX DIRECTORY
表选项来加快速度,CREATE TABLE
。参见 Section 15.1.20, “CREATE TABLE Statement”。 -
BLOB
和TEXT
列可以建立索引。 -
索引列中允许存在
NULL
值。每个键占用 0 到 1 个字节。 -
每个字符列可以有不同的字符集。参见 Chapter 12, Character Sets, Collations, Unicode。
-
MyISAM
索引文件中有一个标志,指示表是否正确关闭。如果使用myisam_recover_options
系统变量启动mysqld,则在打开时会自动检查MyISAM
表,并在表未正确关闭时进行修复。 -
myisamchk如果使用
--update-state
选项运行,则会标记表为已检查。myisamchk --fast仅检查那些没有此标记的表。 -
myisamchk --analyze存储部分键的统计信息,以及整个键的统计信息。
-
myisampack可以压缩
BLOB
和VARCHAR
列。
MyISAM
还支持以下功能:
-
支持真正的
VARCHAR
类型;VARCHAR
列以一个或两个字节存储的长度开始。 -
带有
VARCHAR
列的表可能具有固定或动态行长度。 -
表中
VARCHAR
和CHAR
列的长度之和可以达到 64KB。 -
任意长度的
UNIQUE
约束。
附加资源
- 专门针对
MyISAM
存储引擎的论坛可在forums.mysql.com/list.php?21
找到。
18.2.1 MyISAM 启动选项
下列选项可用于更改MyISAM
表的行为。有关更多信息,请参见mysqld的第 7.1.7 节,“服务器命令选项”。
表 18.3 MyISAM 选项和变量参考
名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
---|---|---|---|---|---|---|
bulk_insert_buffer_size | 是 | 是 | 是 | 两者 | 是 | |
concurrent_insert | 是 | 是 | 是 | 全局 | 是 | |
delay_key_write | 是 | 是 | 是 | 全局 | 是 | |
have_rtree_keys | 是 | 全局 | 否 | |||
key_buffer_size | 是 | 是 | 是 | 全局 | 是 | |
log-isam | 是 | 是 | ||||
myisam-block-size | 是 | 是 | ||||
myisam_data_pointer_size | 是 | 是 | 是 | 全局 | 是 | |
myisam_max_sort_file_size | 是 | 是 | 是 | 全局 | 是 | |
myisam_mmap_size | 是 | 是 | 是 | 全局 | 否 | |
myisam_recover_options | 是 | 是 | 是 | 全局 | 否 | |
myisam_repair_threads | 是 | 是 | 是 | 两者 | 是 | |
myisam_sort_buffer_size | 是 | 是 | 是 | 两者 | 是 | |
myisam_stats_method | 是 | 是 | 是 | 两者 | 是 | |
myisam_use_mmap | 是 | 是 | 是 | 全局 | 是 | |
tmp_table_size | 是 | 是 | 是 | 两者 | 是 | |
名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
下列系统变量影响MyISAM
表的行为。有关更多信息,请参见第 7.1.8 节,“服务器系统变量”。
-
bulk_insert_buffer_size
用于批量插入优化中使用的树缓存大小。
注
这是每个线程的限制!
-
delay_key_write=ALL
在任何
MyISAM
表的写入之间不要刷新键缓冲区。注
如果这样做,您不应该从另一个程序(例如从另一个 MySQL 服务器或使用myisamchk)访问
MyISAM
表格,当表格正在使用时。这样做会导致索引损坏。使用--external-locking
并不能消除这种风险。 -
myisam_max_sort_file_size
MySQL 在重新创建
MyISAM
索引时允许使用的临时文件的最大大小(在REPAIR TABLE
、ALTER TABLE
或LOAD DATA
期间)。如果文件大小大于此值,则使用键缓存而不是创建索引,这会更慢。该值以字节为单位给出。 -
myisam_recover_options=*
mode*
设置自动恢复崩溃的
MyISAM
表的模式。 -
myisam_sort_buffer_size
设置在恢复表格时使用的缓冲区的大小。
如果您使用设置了myisam_recover_options
系统变量的值启动mysqld,则自动恢复将被激活。在这种情况下,当服务器打开MyISAM
表时,它会检查表是否标记为崩溃,或者表的打开计数变量不为 0 且您正在以禁用外部锁定的方式运行服务器。如果这两个条件中的任何一个为真,则会发生以下情况:
-
服务器检查表格是否有错误。
-
如果服务器发现错误,则尝试进行快速表修复(带排序但不重新创建数据文件)。
-
如果由于数据文件中的错误(例如重复键错误)而导致修复失败,则服务器会再次尝试,这次重新创建数据文��。
-
如果修复仍然失败,服务器会再次尝试使用旧的修复选项方法(逐行写入而不排序)。这种方法应该能够修复任何类型的错误,并且对磁盘空间要求低。
如果恢复无法从先前完成的语句中恢复所有行,并且您没有在myisam_recover_options
系统变量的值中指定FORCE
,则自动修复将在错误日志中中止并显示错误消息:
Error: Couldn't repair table: test.g00pages
如果您指定了FORCE
,则会写入类似于以下的警告:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
如果自动恢复值包括BACKUP
,则恢复过程会创建形如*
tbl_name-datetime*.BAK
的文件。您应该有一个cron脚本,自动将这些文件从数据库目录移动到备份介质。
18.2.2 键所需的空间
MyISAM
表使用 B 树索引。您可以粗略计算索引文件的大小为 (key_length+4)/0.67
,对所有键求和。这是最坏情况下的情况,当所有键按排序顺序插入时,表中没有任何压缩键。
字符串索引是空间压缩的。如果第一个索引部分是字符串,则也进行前缀压缩。空间压缩使索引文件比最坏情况下的数字小,如果字符串列有很多尾随空格或是一个VARCHAR
列,没有始终使用到完整长度。前缀压缩用于以字符串开头的键。前缀压缩有助于处理具有相同前缀的许多字符串。
在 MyISAM
表中,您还可以通过在创建表时指定 PACK_KEYS=1
表选项来对数字进行前缀压缩。数字以高字节优先存储,因此当您有许多整数键具有相同前缀时,这很有帮助。
18.2.3 MyISAM 表存储格式
原文:
dev.mysql.com/doc/refman/8.0/en/myisam-table-formats.html
18.2.3.1 静态(固定长度)表特性
18.2.3.2 动态表特性
18.2.3.3 压缩表特性
MyISAM
支持三种不同的存储格式。其中两种,固定和动态格式,根据你使用的列类型自动选择。第三种,压缩格式,只能使用myisampack实用程序创建(参见第 6.6.6 节,“myisampack — 生成压缩的只读 MyISAM 表”)。
当你使用CREATE TABLE
或ALTER TABLE
创建没有BLOB
或TEXT
列的表时,可以使用ROW_FORMAT
表选项强制表格式为FIXED
或DYNAMIC
。
查看第 15.1.20 节,“CREATE TABLE 语句”,了解ROW_FORMAT
的信息。
你可以使用myisamchk的--unpack
选项来解压缩MyISAM
表;查看第 6.6.4 节,“myisamchk — MyISAM 表维护实用程序”获取更多信息。
18.2.3.1 静态(固定长度)表特性
静态格式是MyISAM
表的默认格式。当表中不包含可变长度列(VARCHAR
、VARBINARY
、BLOB
或TEXT
)时使用。每行使用固定字节数存储。
在三种MyISAM
存储格式中,静态格式是最简单和最安全(最不容易损坏)的。由于在磁盘上很容易找到数据文件中的行,它也是磁盘上最快的格式:根据索引中的行号查找行时,将行号乘以行长度以计算行位置。此外,在扫描表时,每次磁盘读取操作都可以很容易地读取恒定数量的行。
如果在 MySQL 服务器写入固定格式的MyISAM
文件时计算机崩溃,安全性得到证明。在这种情况下,myisamchk可以轻松确定每行的起始和结束位置,因此通常可以回收除部分写入的行之外的所有行。MyISAM
表索引始终可以根据数据行重建。
注意
仅适用于没有BLOB
或TEXT
列的表的固定长度行格式。创建具有此类列的表并使用显式的ROW_FORMAT
子句不会引发错误或警告;格式规范将被忽略。
静态格式表具有以下特点:
-
CHAR
和VARCHAR
列会被填充到指定的列宽,尽管列类型不会改变。BINARY
和VARBINARY
列会用0x00
字节填充到列宽。 -
NULL
列需要额外的空间来记录它们的值是否为NULL
。每个NULL
列额外占用一位,向最近的字节取整。 -
非常快速。
-
易于缓存。
-
在崩溃后易于重建,因为行位于固定位置。
-
除非删除大量行并希望将空闲磁盘空间返回给操作系统,否则不需要重新组织。要执行此操作,请使用
OPTIMIZE TABLE
或myisamchk -r。 -
通常需要比动态格式表更多的磁盘空间。
-
静态大小行的预期行长度(以字节为单位)通过以下表达式计算:
row length = 1 + (*sum of column lengths*) + (*number of NULL columns* + *delete_flag* + 7)/8 + (*number of variable-length columns*)
delete_flag
在静态行格式的表中为 1。静态表在行记录中使用一个位来表示行是否已被删除。对于动态表,delete_flag
为 0,因为标志位存储在动态行头中。
18.2.3.2 动态表特性
如果MyISAM
表包含任何可变长度列(VARCHAR
、VARBINARY
、BLOB
或TEXT
),或者表是使用ROW_FORMAT=DYNAMIC
表选项创建的,则使用动态存储格式。
动态格式比静态格式稍微复杂,因为每行都有一个标头,指示其长度。当由于更新而使行变长时,行可能会变得碎片化(存储在非连续的片段中)。
您可以使用OPTIMIZE TABLE
或myisamchk -r来对表进行碎片整理。如果您在一个表中频繁访问或更改固定长度列,并且该表还包含一些可变长度列,那么将可变长度列移动到其他表中以避免碎片化可能是一个好主意。
动态格式表具有以下特点:
-
所有字符串列都是动态的,除了长度小于四的列。
-
每行前面都有一个位图,指示哪些列包含空字符串(对于字符串列)或零(对于数值列)。这不包括包含
NULL
值的列。如果字符串列在去除尾随空格后长度为零,或者数值列的值为零,则在位图中标记并不保存到磁盘。非空字符串保存为长度字节加上字符串内容。 -
NULL
列需要额外的空间来记录它们的值是否为NULL
。每个NULL
列额外占用一位,向上取整到最近的字节。 -
比固定长度表通常需要更少的磁盘空间。
-
每行只使用所需的空间。但是,如果一行变得更大,它将被分成所需的碎片,导致行碎片化。例如,如果更新了一行的信息,使行长度增加,那么该行将变得碎片化。在这种情况下,您可能需要定期运行
OPTIMIZE TABLE
或myisamchk -r来提高性能。使用myisamchk -ei获取表统计信息。 -
在崩溃后更难重建比静态格式表,因为行可能会分成许多片段,而且链接(片段)可能丢失。
-
动态大小行的预期行长度使用以下表达式计算:
3 + (*number of columns* + 7) / 8 + (*number of char columns*) + (*packed size of numeric columns*) + (*length of strings*) + (*number of NULL columns* + 7) / 8
每个链接都会有 6 个字节的惩罚。每当更新导致行的扩大时,就会链接一个动态行。每个新链接至少有 20 个字节,所以下一个扩大可能会放在同一个链接中。如果不是,就会创建另一个链接。你可以使用myisamchk -ed来查找链接的数量。所有链接可以通过
OPTIMIZE TABLE
或myisamchk -r来移除。
18.2.3.3 压缩表特性
压缩存储格式是使用myisampack工具生成的只读格式。压缩表可以使用myisamchk解压缩。
压缩表具有以下特性:
-
压缩表占用非常少的磁盘空间。这最小化了磁盘使用,对于使用慢速磁盘(如 CD-ROM)很有帮助。
-
每行都单独压缩,因此几乎没有访问开销。每行的标头占用一到三个字节,取决于表中最大的行。每列的压缩方式不同。通常每列都有不同的哈夫曼树。一些压缩类型包括:
-
后缀空间压缩。
-
前缀空间压缩。
-
值为零的数字使用一位存储。
-
如果整数列中的值范围较小,则使用可能的最小类型存储该列。例如,一个
BIGINT
列(八个字节)可以存储为一个TINYINT
列(一个字节),如果其所有值都在-128
到127
的范围内。 -
如果一列只有一小组可能的值,数据类型将转换为
ENUM
。 -
一列可以使用前述压缩类型的任意组合。
-
-
可用于固定长度或动态长度行。
注意
虽然压缩表是只读的,因此您不能更新或添加表中的行,但 DDL(数据定义语言)操作仍然有效。例如,您仍然可以使用DROP
删除表,使用TRUNCATE TABLE
清空表。
18.2.4 MyISAM 表格问题
原文:
dev.mysql.com/doc/refman/8.0/en/myisam-table-problems.html
18.2.4.1 损坏的 MyISAM 表格
18.2.4.2 未正确关闭表格导致的问题
MySQL 用于存储数据的文件格式经过了广泛测试,但总会有一些情况可能导致数据库表损坏。以下讨论描述了这种情况可能发生的原因以及如何处理。
原文:
dev.mysql.com/doc/refman/8.0/en/corrupted-myisam-tables.html
18.2.4.1 损坏的 MyISAM 表
即使MyISAM
表格式非常可靠(由 SQL 语句对表所做的所有更改都在语句返回之前写入),如果发生以下任何事件,仍然可能出现损坏的表:
-
mysqld进程在写入过程中被终止。
-
发生意外的计算机关闭(例如,计算机被关闭)。
-
硬件故障。
-
您正在使用外部程序(例如myisamchk)同时修改服务器正在修改的表。
-
MySQL 或
MyISAM
代码中的软件错误。
损坏表的典型症状包括:
-
从表中选择数据时出现以下错误:
Incorrect key file for table: '...'. Try to repair it
-
查询在表中找不到行或返回不完整的结果。
您可以使用CHECK TABLE
语句检查MyISAM
表的健康状况,并使用REPAIR TABLE
修复损坏的MyISAM
表。当mysqld未运行时,您还可以使用myisamchk命令检查或修复表。请参阅第 15.7.3.2 节,“CHECK TABLE Statement”,第 15.7.3.5 节,“REPAIR TABLE Statement”,以及第 6.6.4 节,“myisamchk — MyISAM 表维护实用程序”。
如果您的表经常损坏,您应该尝试确定为什么会发生这种情况。最重要的是要知道表是否因意外服务器退出而损坏。您可以通过查看错误日志中最近的重新启动的 mysqld
消息来轻松验证这一点。如果有这样的消息,那么表损坏很可能是服务器死机的结果。否则,损坏可能发生在正常操作期间。这是一个错误。您应该尝试创建一个可重现的测试用例来演示问题。请参阅第 B.3.3.3 节,“如果 MySQL 一直崩溃该怎么办”,以及第 7.9 节,“调试 MySQL”。