好多人在调优Mysql的时候,总是对open_tables和opend_tables两个参数分别不清。

网上好多解释都是这样的:
open_tables:当前打开表的数量
opened_tables:当前已经打开表的数量
 
很简单的解释,可是这两句话看起来有点类似。
 
下面我来解释一下:
open_tables:是当前在缓存中打开表的数量。
opened_tables:是mysql自启动起,打开表的数量。
 
我们知道,假如没有缓存的话,那么mysql服务在每次执行一个语句的时候,都会先打开一个表。当sql语句执行完成后,则把这个表关掉。这就是opend_tables中的值。
 
而open_tables这个值,是mysql在使用缓存的情况下,存储在缓存中的表的个数。
 
我们可以这样做实验:执行flush tables;这个命令是mysql用来刷新缓存的。当这个命令执行后,我们会看到
open_tables这个值被清零了。但是opened_tables这个值还是保持原来值不变。
 
但是当我们关闭mysql服务,再重启后,opened_tables这个值也被清零了。
 
由此,得出上述两个值的结论。
 
这也就是为什么说当open_tables这个值接近于table_open_cache这个值的时候,同时opened_tables的值在不断的增加,这个时候就要考虑增大table_open_cache这个缓存值了。
 
解释如下:
因为open_tables的值接近于table_open_cache,说明分配的缓存已经被用完了。而opened_tables这个值又在高速增加,说明mysql在不断的打开表。也就说明缓存中并没有这些要打开的表。所以说,缓存应该是要增加了。因为如果表在缓存中,那么打开表的时候这两个值是不会增加的。

——————————————————————————————————————————————

这段时间,监控的一个mysql数据库频繁的报警 table_cache_hitrate 小于1%

mysql> show global status like '%table%';
+-----------------------------------------+-----------+
| Variable_name                           | Value     |
+-----------------------------------------+-----------+
| Created_tmp_disk_tables                 | 1062135   |
| Created_tmp_tables                      | 34492864  |
| Open_table_definitions                  | 452       |
| Open_tables                             | 515       |
| Opened_table_definitions                | 226373    |
| Opened_tables                           | 254733    |
| Performance_schema_table_handles_lost   | 0         |
| Performance_schema_table_instances_lost | 0         |
| Slave_open_temp_tables                  | 0         |
| Table_locks_immediate                   | 188997447 |
| Table_locks_waited                      | 421288    |
+-----------------------------------------+-----------+

关于 open_tables: 当前打开的表的数量; opened_tables:服务器启动以来打开的表的数量。

关于table_open_cache 和 max_connections :

MySQL is multi-threaded, so there may be many clients issuing queries for a  given table simultaneously. To minimize the problem with multiple client  sessions having different states on the same table, the table is opened  independently by each concurrent session. This uses additional memory but  normally increases performance. With MyISAMtables,  one extra file descriptor is required for the data file for each client that has  the table open. (By contrast, the index file descriptor is shared between all  sessions.)

The and system variables affect the maximum  number of files the server keeps open. If you increase one or both of these  values, you may run up against a limit imposed by your operating system on the  per-process number of open file descriptors. Many operating systems permit you  to increase the open-files limit, although the method varies widely from system  to system. Consult your operating system documentation to determine whether it  is possible to increase the limit and how to do so.

is related to . For example, for 200 concurrent  running connections, specify a table cache size of at least 200 * N, where Nis the maximum number of tables per join  in any of the queries which you execute. You must also reserve some extra file  descriptors for temporary tables and files.

msql 5.5

设置 innodb_file_per_table =0 ,所有表使用公共的表空间。

可以看一下 open_tables 和 opened_tables的变化:

我们设置 table_open_cache 的值为30,来看一下变化的情况:

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 26    |
| Opened_tables | 33    |
+---------------+-------+
2 rows in set (0.00 sec)

mysql> select * from test limit 2;
+-------+
| col   |
+-------+
| testa |
| ddd   |
+-------+
2 rows in set (0.02 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 27    |
| Opened_tables | 34    |
+---------------+-------+
2 rows in set (0.00 sec)

-----------------------可以看到,打开一个表的时候,这两个状态的值是增长的---------

当open_tables 达到 table_open_cache的时候看一下变化:

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 38    |
+---------------+-------+
2 rows in set (0.00 sec)

mysql> select * from test8 limit 2;
Empty set (0.03 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 39    |
+---------------+-------+

-----------------------这时候,就只有 opened_tables 增长了-----------------

当 open_tables 达到 table_open_cache,有新的表需要打开的时候,就需要对已经存在于cache中的表 close, 具体的解释如下:

MySQL closes an unused table and removes it from the table cache under the  following circumstances:

When the cache is full and a thread tries to open a table that is not in the  cache.

When the cache contains more than entries and a table in the cache is no  longer being used by any threads.

When a table flushing operation occurs. This happens when someone issues a statement or executes a or command.

When the table cache fills up, the server uses the following procedure to  locate a cache entry to use:

Tables that are not currently in use are released, beginning with the table  least recently used.

If a new table needs to be opened, but the cache is full and no tables can be  released, the cache is temporarily extended as necessary. When the cache is in a  temporarily extended state and a table goes from a used to unused state, the  table is closed and released from the cache

我们可以手工打开超过table_open_cache 的新表,看一下是否会把之前打开的表给踢出cache:

mysql> select * from test2; 
Empty set (0.00 sec)

mysql> select * from test3; 
Empty set (0.00 sec)

mysql> select * from test4; 
Empty set (0.00 sec)

mysql> select * from test5; 
Empty set (0.00 sec)

mysql> select * from test6; 
Empty set (0.00 sec)

mysql> select * from test7; 
Empty set (0.00 sec)

mysql> select * from test8; 
Empty set (0.01 sec)

mysql> select * from test9; 
Empty set (0.00 sec)

mysql> select * from test10; 
Empty set (0.00 sec)

mysql> select * from test11; 
Empty set (0.00 sec)

mysql> select * from test12; 
Empty set (0.00 sec)

mysql> select * from test13; 
Empty set (0.00 sec)

mysql> select * from test14; 
Empty set (0.00 sec)

mysql> select * from test15; 
Empty set (0.00 sec)

mysql> select * from test16; 
Empty set (0.00 sec)

mysql> select * from test17; 
Empty set (0.00 sec)

mysql> select * from test18; 
Empty set (0.00 sec)

mysql> select * from test19; 
Empty set (0.00 sec)

mysql> select * from test20; 
Empty set (0.00 sec)

mysql> select * from test21; 
Empty set (0.00 sec)

mysql> select * from test22; 
Empty set (0.00 sec)

mysql> select * from test23; 
Empty set (0.00 sec)

mysql> select * from test24; 
Empty set (0.00 sec)

mysql> select * from test25; 
Empty set (0.00 sec)

mysql> select * from test26; 
Empty set (0.00 sec)

mysql> select * from test27; 
Empty set (0.00 sec)

mysql> select * from test28; 
Empty set (0.00 sec)

mysql> select * from test29; 
Empty set (0.00 sec)

mysql> select * from test30; 
Empty set (0.00 sec)

mysql> select * from test31; 
Empty set (0.00 sec)

mysql> select * from test32; 
Empty set (0.00 sec)

mysql> select * from test33; 
Empty set (0.00 sec)

mysql> select * from test34; 
Empty set (0.00 sec)

mysql> select * from test35; 
Empty set (0.00 sec)

mysql> select * from test36; 
Empty set (0.00 sec)

mysql> select * from test37; 
Empty set (0.00 sec)

mysql> select * from test38; 
Empty set (0.00 sec)

mysql> select * from test39; 
Empty set (0.00 sec)

mysql> select * from test40; 
Empty set (0.00 sec)

mysql> select * from test41; 
Empty set (0.00 sec)

mysql> select * from test42; 
+------+
| id   |
+------+
|    3 |
+------+
1 row in set (0.00 sec)

再次查询:

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 80    |
+---------------+-------+

mysql> select * from test limit 2;
+-------+
| col   |
+-------+
| testa |
| ddd   |
+-------+
2 rows in set (0.00 sec)

mysql> select * from test5 limit 2;
+------+-------+
| id   | name  |
+------+-------+
| 1000 | test4 |
| 1001 | test4 |
+------+-------+
2 rows in set (0.00 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 80    |
+---------------+-------+

----------这里我们新打开的表的数量远远超过了30,但是重新查询之前打开的表,open_tables 没有增长,按照上面的理论,应该是cache临时扩张,不过找不到一些直接的状态值来查看这个。

这里我们可以继续做实验,我这里重新创建了一个database,重新创建了41个表,然后对41个表执行查询,我们再看:

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 121   |

重新查询之前打开过的表:

mysql> select * from test7 limit 3;
+------+-------+
| id   | name  |
+------+-------+
|  500 | test1 |
|  501 | test1 |
|  502 | test1 |
+------+-------+

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 122   |
+---------------+-------+
2 rows in set (0.00 sec)

mysql>  select * from test6 limit 3;
+------+-------+
| id   | name  |
+------+-------+
|    1 | test4 |
|    2 | test4 |
|    3 | test4 |
+------+-------+
3 rows in set (0.00 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 123   |

--------- 这里已经可以很清楚看到 cache满之后,会按照 最近最少使用的原则 从cache中丢弃掉。

对于opened_tables 的增长,临时表也贡献了非常多。对于内部临时表,有下面的文档:

In some cases, the server creates internal temporary tables  while processing queries. Such a table can be held in memory   and processed by the MEMORYstorage engine,  or stored on disk and processed by the  MyISAMstorage engine. The server may          create a temporary table initially as an in-memory table, then  convert it to an on disk table if it becomes too large. Users  have no direct control over when the server creates an internal temporary table or which storage engine the server  uses to manage it.

临时表的创建:

Temporary tables can be created under conditions such as  these:

If there is an ORDER BYclause and a different GROUP BYclause, or if the  ORDER BYor GROUP BYcontains columns from tables other than the first table in  the join queue, a temporary table is created.

DISTINCTcombined with ORDER   BYmay require a temporary table.

If you use the SQL_SMALL_RESULToption,   MySQL uses an in-memory temporary table, unless the query   also contains elements (described later) that require  on-disk storage.To determine whether a query requires a temporary table, use  EXPLAINand check the Extracolumn to see whether it says  Using temporary. See  Section 8.8.1, “Optimizing Queries with EXPLAIN”.

如果查询中使用了 order by 、group by 、distinct 会生成内部临时表。

测试一下:

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 124   |
+---------------+-------+

mysql> select * from test42;
+------+
| id   |
+------+
|    3 |
+------+

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 124   |
+---------------+-------+

mysql> select * from test42 order by id;
+------+
| id   |
+------+
|    3 |
+------+
1 row in set (0.00 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 125   |
+---------------+-------+

opened_tables 增加了1.

mysql> select distinct name from test5;
+-------+
| name  |
+-------+
| test4 |
| test1 |
+-------+
2 rows in set (1.43 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 126   |
+---------------+-------+

mysql> select name,count(*) from test5 group by name;
+-------+----------+
| name  | count(*) |
+-------+----------+
| test1 |   217081 |
| test4 |   999000 |
+-------+----------+
2 rows in set (1.18 sec)

mysql> show global status like 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 30    |
| Opened_tables | 126   |
+---------------+-------+

mysql> explain select name,count(*) from test5 group by name;
+----+-------------+-------+------+---------------+------+---------+------+---------+---------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra                           |
+----+-------------+-------+------+---------------+------+---------+------+---------+---------------------------------+
|  1 | SIMPLE      | test5 | ALL  | NULL          | NULL | NULL    | NULL | 1216813 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+---------+---------------------------------+

可以看到,如果前一次查询使用 order by 、group by、distinct 生成了临时表,则后面使用这些语法是不会再生成新的临时表。

使用 explain 查看语句执行计划的时候,如果 Extra 中有 Using temporary 的语句,则此语句使用了内部临时表。

对于隐式的临时表的创建,可以通过状态变量:Created_tmp_tables 来查看增长。

mysql>  show global status like '%created%%table%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Created_tmp_disk_tables | 1063051  |
| Created_tmp_tables      | 34514321 |
+-------------------------+----------+
2 rows in set (0.00 sec)

对于innodb_file_per_table=1 , 结果大致一样。

对于监控指标: table_cache_hitrate = open_tables /  opened_tables ;

在5.6 版本中,引入了状态变量:

对于这一指标的监控更加方便。

open_table与opened_table --2的更多相关文章

  1. open_table与opened_table

    好多人在调优Mysql的时候,总是对open_tables和opend_tables两个参数分别不清. 网上好多解释都是这样的:open_tables:当前打开表的数量opened_tables:当前 ...

  2. open_table

    /* Open a table. SYNOPSIS open_table() thd Thread context. table_list Open first table in list. acti ...

  3. MySQL调优基础, 与hikari数据库连接池配合

    1.根据硬件配置系统参数 wait_timeout  非交互连接的最大存活时间, 10-30min max_connections   全局最大连接数 默认100 根据情况调整 back_log   ...

  4. MySQL备份锁

    无论逻辑备份还是物理备份,为了获取一致性位点,都强依赖于FTWRL(Flush Table With Read Lock).这个锁杀伤力非常大,因为持有锁的这段时间,整个数据库实质上不能对外提供写服务 ...

  5. rabbitmq启动异常之error,{not_a_dets_file recovery.dets

    中午,公司群里面测试人员@笔者说,早上测试服务器异常,MQ起不来,重启os了也起不来,报错,上去看下了早上又因为内存oom被内核killed了,启动了下,确实启动报错,erl vm进程起来了,但是be ...

  6. Mysql查询阻塞初探

    第一次值班,报警打电话给我说,数据库复制延时一个多小时,那个时候是半夜啊,但我还是很清醒的起来,开机.vpn.登录.show processlist,结果发现情况是这样的: 红线框表示的是当前每个线程 ...

  7. 【网络资料】Astar算法详解

    关于A*算法,很早就想写点什么,可是貌似天天在忙活着什么,可事实又没有做什么,真是浮躁啊!所以今晚还是来写一下总结吧! A*算法是很经典的只能启发式搜索算法,关于只能搜索算法和一般的搜索算法(例如DF ...

  8. struct TABLE

    struct TABLE { TABLE() {} /* Remove gcc warning */ TABLE_SHARE *s; handler *file; TABLE *next, *prev ...

  9. MySQL锁系列3 MDL锁

    http://www.cnblogs.com/xpchild/p/3790139.html   MySQL为了保护数据字典元数据,使用了metadata lock,即MDL锁,保证在并发的情况下,结构 ...

随机推荐

  1. String中intern的方法

    首先查看官方API那个的解释: ——————————————————————————————————————— intern public String intern() 返回字符串对象的规范化表示形 ...

  2. 【转】DBCP连接池原理分析

    ---------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 JDBC 3. DB ...

  3. (七)学习MVC之CodeFirst迁移更新数据库

    1.首先在程序包管理控制台输入:enable-migrations -force ,然后回车: 问题1: The EntityFramework package is not installed on ...

  4. 也用 Log4Net 之将自定义属性记录到文件中 (三)

    也用 Log4Net  之将自定义属性记录到文件中 (三)  即解决了将自定义属性记录到数据库之后.一个新的想法冒了出来,自定义属性同样也能记录到文件中吗?答案是肯定的,因为Log4Net既然已经考虑 ...

  5. MVC的EF编辑,不用查询直接修改

    EF中会为每个 管理的 实体对象 创建一个代理包装类对象,其中会跟踪 实体对象 的状态和每个属性的状态: 一.通常使用EF更新的方式,先查询出要修改的数据,然后再修改新的值:实体对象被修改的属性 在 ...

  6. MySQL数据库的同步配置+MySql读写分离

    使用mysql主从复制的好处有: 1.采用主从服务器这种架构,稳定性得以提升.如果主服务器发生故障,我们可以使用从服务器来提供服务. 2.在主从服务器上分开处理用户的请求,可以提升数据处理效率. 3. ...

  7. selenium+testNG+Ant

    好几天没写了,抽时间写下,也好有个总结: 1.selenium+testNG+Ant (1)ant 是构建工具 他的作用就是运行你配置好的东西 而tentng.xml你可以认为他是管理test的一个配 ...

  8. ThoughtWorks(中国)程序员读书雷达 —— 书籍下载整理

    ThoughtWorks(中国)程序员读书雷达 http://agiledon.github.io/blog/2013/04/17/thoughtworks-developer-reading-rad ...

  9. JSF2.0 タグ一覧 (h:panelGrid) 編

    JSF の HTML (UIComponent) 系タグにはテーブルを作成するタグが2種類用意されています.これらのタグと固有機能系タグを組み合わせることでテーブルを使用した画面を作成可能です. 6. ...

  10. 50道经典的JAVA编程题 (16-20)

    50道经典的JAVA编程题 (16-20),用了快一个下午来做这10道题了,整理博客的时间貌似大于编程的时间啊..哈哈 [程序16]Nine.java 题目:输出9*9口诀. 1.程序分析:分行与列考 ...