我想降级 AWS 实例以节省成本,但是由于表和工作负载(逻辑备份)的数量,InnoDB 数据字典变得非常大。
mysql> SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES;
+----------+
| COUNT(*) |
+----------+
| 1020034 |
+----------+
1 row in set (4.61 sec)
mysql> SELECT COUNT(*) FROM information_schema.INNODB_SYS_INDEXES;
+----------+
| COUNT(*) |
+----------+
| 2628181 |
+----------+
1 row in set (4.99 sec)
-
mysql> SHOW GLOBAL VARIABLES LIKE 'table_%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| table_definition_cache | 400 |
| table_open_cache | 1 |
| table_open_cache_instances | 1 |
+----------------------------+-------+
3 rows in set (0.00 sec)
mysql> SHOW GLOBAL STATUS LIKE 'Open%table%';
+--------------------------+----------+
| Variable_name | Value |
+--------------------------+----------+
| Open_table_definitions | 400 |
| Open_tables | 1 |
| Opened_table_definitions | 2312885 |
| Opened_tables | 22403462 |
+--------------------------+----------+
4 rows in set (0.00 sec)
-
mysql> SHOW GLOBAL STATUS LIKE 'Innodb_mem_dictionary';
+-----------------------+------------+
| Variable_name | Value |
+-----------------------+------------+
| Innodb_mem_dictionary | 4517841711 |
+-----------------------+------------+
1 row in set (0.00 sec)
对于 InnoDB,table_definition_cache 充当 InnoDB 数据字典缓存中打开表实例数量的软限制。如果打开表实例的数量超过了table_definition_cache设置,LRU机制开始将表实例标记为逐出,并最终将其从数据字典缓存中移除。
知道为什么这没有发生吗?我想知道在这种情况下启用 innodb_file_per_table 是否有帮助。
一些额外的信息:
mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name | Value |
+-------------------------+------------+
| innodb_buffer_pool_size | 8589934592 |
+-------------------------+------------+
1 row in set (0.00 sec)
mysql> SELECT @@version, @@version_comment;
+--------------------+---------------------------------------------------------------------------------------------------+
| @@version | @@version_comment |
+--------------------+---------------------------------------------------------------------------------------------------+
| 5.6.30-76.3-56-log | Percona XtraDB Cluster (GPL), Release rel76.3, Revision aa929cb, WSREP version 25.16, wsrep_25.16 |
+--------------------+---------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
-
# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
# free -m
total used free shared buff/cache available
Mem: 14881 14239 326 6 315 378
Swap: 4095 1237 2858
# ps -o %mem,rss,vsize -C mysqld
%MEM RSS VSZ
94.2 14364148 16262404
一百万张桌子?!!仅此一项就可能使 MySQL 窒息。你在做什么?
运行这个;它可能会提供关于它是表、分区还是其他什么的线索:
数据库或表名称的模式可能很明显。以 like 结尾
#p#p200805
的名称是分区名称。如果是表或数据库,让我们讨论如何做。请提供一些关于您的表格的提示。在此之前,我将提供一些通用建议。不是每个实体一个表,而是一个表。其中有一个 id 指示涉及哪个实体。(“实体”是“用户”、“公司”或您创建新表所基于的任何内容。)
然后,为了摆脱一个表,你将需要大量的磁盘空间和停机时间来将数百万个表复制到少数几个表中,同时添加 id。
如果是分区,让我们讨论一下。单个表中超过 50 个分区会导致效率低下。少于一百万行的表不应(通常)进行分区。请提供
SHOW CREATE TABLE
,因为有很多可能的问题。我在这里给出一些答案。警告:我所说的大部分内容对于8.0 版都是无效的,而且它是集成的数据字典。许多数据库或表或分区不是什么大问题。
看起来这个变量没有正常工作,Percona 在 5.5 中的先前实现(innodb_dict_size_limit)更可靠:
更新:2016 年 10 月 30 日星期日 20:07:20 GMT
实际上,这目前不会从字典缓存中删除带有 FOREIGN KEYS 的表,我们每个数据库有 76 个带有 FOREIGN KEYS 的表:
参考资料: