新年第一篇。
我们找到一个刚刚全部刷新的数据库(或者重启的数据库),有些东西我们可以先不看文档,用实验来看看效果。打开会话A。图1
图1
再开另外一个session会话B,会话B打开并没有占用open_tables,执行opened_tables的时候占用了一个。 图2
图2
回到第一个会话,会话A,我们看到open_tables增加了,opened_tables没有变化。所以可以推断出opened_tables是当前会话的。而open_tables是全局的。 图3
图3
继续在第一个会话A操作。创建一个database xuexiaogang1后,可以看到opened_tables增加了1.这个好理解。那么opened_tables也增加了1. 图4
图4
我们到会话B上去创建一个database,实验一下。可以看到opened_tables增加了1(其实这里从4到5的过程没有显示,其实是在执行create database之前已经是全局的4了)。那么opened_tables也增加了1. 图5
图5
回到第一个会话中看到,的确也是open_tables增加了,而opened_tables没有变化。
图6
执行了一下use xuexiaogang1 opened_tables增加了21,所以全局也增加了21,这里应该是有一些系统字典的相关加载,具体的还没研究明白。 图6
图6
在会话B中,use xuexiaogang2 opened_tables增加了6,所以全局也增加了6。为什么两个空库use后加载的不一样,还有待研究。 图7
图7
继续另外一个实验,一旦use database以后opened_tables和opened_tables都会增加,这个时候再次select该database下的table 不会造成opened_tables和opened_tables的增加。如下图8、 图9
图8
图9
结论:我们database下的table不要有很多,通常建议50个左右,不要动辄200多,甚至300或者400的表。一旦use database会大量打开表,而且这些打开的还和会话有关,会话数越多,造成打开的全局数量也越多。这是最佳实践。也定义了MySQL的场景,不要复杂的ER图关系。一旦表打开数据量超过了table_open_cache,那么当Open_tables值大于table_open_cache值时,每次新的session打开表,有一些无法命中table cache,而不得不重新打开表。可能会导致的线程处于opening tables状态。