本文來自:http://chenxu.yo2.cn/articles/mysql_table_cache.html
一、狀態值和變量:
1.1
在MySQL的show status中有2個狀態值:Open_tables和Opened_tables。這2個值代表的意思如下:
Open_tables :代表當前打開表的數量。
Opened_tables:代表自從MySQL啟動后,打開表的數量。
關於MySQL怎么打開關閉表的具體細節參考文檔:<How MySQL Opens and Closes Tables>。
(1)對於myisam存儲引擎,打開1張表需要2個文件描述符(一個.MYD文件,一個.MYI文件)。
(2)對於innodb存儲引擎,開啟表的獨立表空間(innodb_file_per_table)打開1張表只需要1個文件描述符(一個.ibd文件)。
【MySQL Variable】
對於上面的狀態值,對應的5.1.3版本后的MySQL變量參數為table_open_cache,而早期版本為:table_cache,該參數值的代表MySQL可以緩存的打開表時候的最大文件描述符。
1.2
在MySQL 5.1.3之后,還添加了2個狀態值:Open_table_definitions和Opened_table_definitions。這2個值代表的意思如下:
Open_table_definitions :代表當前緩存了多少.frm文件。
Opened_table_definitions:代表自從MySQL啟動后,緩存了.frm文件的數量。
需要注意的是.frm文件是MySQL用於存放表結構的文件,對應myisam和innodb存儲引擎都必須有的。
【MySQL Variable】
對於上面的狀態值,對應的5.1.3版本后的MySQL變量參數為table_definition_cache,該參數值的代表MySQL可以緩存的表定義的數量。和前面的table cache不同的是,表定義的緩存占用空間很小,而且不需要使用文件描述符,也就是只要打開.frm文件,緩存表定義,然后就可以關閉.frm文件。
1.3
另外,還有2個狀態值:Open_files和Opened_files。這2個值的意思同上類似:
Open_files :代表當前打開的文件。對應存儲引擎(如:innodb)使用存儲引擎自己內部函數打開的話,這個值是不會增加的。
Opened_files:代表使用MySQL的my_open()函數打開過的文件數。如果不是使用這個函數打開文件的話,這個值是不會增加的。
【MySQL Variable】
對於上面的狀態值,對應的MySQL變量參數為open_files_limit。
二、測試
測試的MySQL版本:
mysql> select version();
+------------+
| version() |
+------------+
| 5.1.47-log |
+------------+
1 row in set (0.00 sec)
2.1 myisam存儲引擎
2.1.1
重啟MySQL服務器,可以看到啟動時候MySQL已經自動打開相關的系統表。
mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Open_table_definitions | 15 |
| Opened_table_definitions | 15 |
+--------------------------+-------+
2 rows in set (0.00 sec)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 8 |
| Opened_tables | 15 |
+---------------+-------+
2 rows in set (0.00 sec)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_files | 19 |
| Opened_files | 62 |
+---------------+-------+
2 rows in set (0.00 sec)
在上面的狀態輸出,可以看到Open_tables的值為8,代表了當前打開了8張表,同樣的通過mysqladmin status命令也可以看到:
[mysql@xentest8-vm1 test]$ mysqladmin status
Uptime: 631 Threads: 2 Questions: 14 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.22
可以通過SHOW OPEN TABLES命令查看,當前的table cache到底打開了哪些表:
mysql> show open tables;
+----------+--------------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+--------------+--------+-------------+
| mysql | servers | 0 | 0 |
| mysql | db | 0 | 0 |
| mysql | host | 0 | 0 |
| mysql | columns_priv | 0 | 0 |
| mysql | user | 0 | 0 |
| mysql | procs_priv | 0 | 0 |
| mysql | event | 0 | 0 |
| mysql | tables_priv | 0 | 0 |
+----------+--------------+--------+-------------+
8 rows in set (0.00 sec)
可以看到打開了mysql庫里面的8張系統表(都是myisam存儲引擎),另外,還可以通過lsof(lsof的用法參見<使用lsof查找打開的文件>)查看MySQL打開的對應文件:
[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/mysql/
mysqld 14683 mysql 16u REG 253,1 2048 87889757 /home/mysql/mysql-5.1.47/data/mysql/host.MYI
mysqld 14683 mysql 17u REG 253,1 0 87889758 /home/mysql/mysql-5.1.47/data/mysql/host.MYD
mysqld 14683 mysql 18u REG 253,1 2048 87889760 /home/mysql/mysql-5.1.47/data/mysql/user.MYI
mysqld 14683 mysql 19u REG 253,1 380 87889761 /home/mysql/mysql-5.1.47/data/mysql/user.MYD
mysqld 14683 mysql 20u REG 253,1 5120 87889754 /home/mysql/mysql-5.1.47/data/mysql/db.MYI
mysqld 14683 mysql 21u REG 253,1 880 87889755 /home/mysql/mysql-5.1.47/data/mysql/db.MYD
mysqld 14683 mysql 22u REG 253,1 4096 87889772 /home/mysql/mysql-5.1.47/data/mysql/tables_priv.MYI
mysqld 14683 mysql 23u REG 253,1 0 87889773 /home/mysql/mysql-5.1.47/data/mysql/tables_priv.MYD
mysqld 14683 mysql 24u REG 253,1 4096 87889775 /home/mysql/mysql-5.1.47/data/mysql/columns_priv.MYI
mysqld 14683 mysql 25u REG 253,1 0 87889776 /home/mysql/mysql-5.1.47/data/mysql/columns_priv.MYD
mysqld 14683 mysql 26u REG 253,1 4096 87889808 /home/mysql/mysql-5.1.47/data/mysql/procs_priv.MYI
mysqld 14683 mysql 27u REG 253,1 0 87889809 /home/mysql/mysql-5.1.47/data/mysql/procs_priv.MYD
mysqld 14683 mysql 28u REG 253,1 1024 87889769 /home/mysql/mysql-5.1.47/data/mysql/servers.MYI
mysqld 14683 mysql 29u REG 253,1 0 87889770 /home/mysql/mysql-5.1.47/data/mysql/servers.MYD
mysqld 14683 mysql 30u REG 253,1 2048 87889817 /home/mysql/mysql-5.1.47/data/mysql/event.MYI
mysqld 14683 mysql 31u REG 253,1 0 87889818 /home/mysql/mysql-5.1.47/data/mysql/event.MYD
2.1.2
接着打開一張myisam存儲引擎的表:
mysql> select count(*) from myisam_1;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';
# 可以看到Opened_table_definitions/Opened_table_definitions/Open_tables/Opened_tables的值都加1
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Open_table_definitions | 16 | +1
| Opened_table_definitions | 16 | +1
+--------------------------+-------+
2 rows in set (0.00 sec)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 9 | +1
| Opened_tables | 16 | +1
+---------------+-------+
2 rows in set (0.00 sec)
# 可以看到Open_files的值(19+2)加2,Opened_files的值(62+3)加3
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_files | 21 | +2(MYI,MYD)
| Opened_files | 65 | +3(MYI,MYD,FRM)
+---------------+-------+
2 rows in set (0.00 sec)
mysql> show create table myisam_1\G
*************************** 1. row ***************************
Table: myisam_1
Create Table: CREATE TABLE `myisam_1` (
`a` int(11) DEFAULT NULL,
KEY `idx_myisam_1` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show open tables from test;
+----------+----------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+----------+--------+-------------+
| test | myisam_1 | 0 | 0 |
+----------+----------+--------+-------------+
1 row in set (0.00 sec)
[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/test/
mysqld 14683 mysql 33u REG 253,1 1024 87851510 /home/mysql/mysql-5.1.47/data/test/myisam_1.MYI
mysqld 14683 mysql 34u REG 253,1 0 87851511 /home/mysql/mysql-5.1.47/data/test/myisam_1.MYD
# 可見,除了需要打開.frm文件(打開,緩存后,就關閉,所以Open_files沒有+3,只有+2),對於myisam存儲引擎,打開1張表需要2個文件描述符(一個.MYD文件,一個.MYI文件)
2.1.3
對應table cache中的緩存的表,可以通過flush tables命令來把它人工移出table cache:
mysql> flush tables myisam_1;
Query OK, 0 rows affected (0.00 sec)
mysql> show open tables from test;
Empty set (0.00 sec)
mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';
# 可以看到Open_table_definitions和Open_tables的值都減1
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Open_table_definitions | 15 | -1
| Opened_table_definitions | 16 |
+--------------------------+-------+
2 rows in set (0.00 sec)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 8 | -1
| Opened_tables | 16 |
+---------------+-------+
2 rows in set (0.00 sec)
# 可以看到Open_files的值(21-2)減2
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_files | 19 | -2 (MYI,MYD)
| Opened_files | 65 |
+---------------+-------+
2 rows in set (0.00 sec)
[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/test/ | wc -l
0
2.2 innodb存儲引擎
2.2.1
打開一張innodb存儲引擎的表:
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.00 sec)
mysql> select count(*) from t0001;
+----------+
| count(*) |
+----------+
| 2 |
+----------+
1 row in set (0.01 sec)
mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';
# 可以看到Opened_table_definitions/Opened_table_definitions/Open_tables/Opened_tables的值都加1
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Open_table_definitions | 16 | +1
| Opened_table_definitions | 17 | +1
+--------------------------+-------+
2 rows in set (0.00 sec)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 9 | +1
| Opened_tables | 17 | +1
+---------------+-------+
2 rows in set (0.00 sec)
# 可以看到Open_files的值不變(即innodb使用存儲引擎自己內部函數打開的話,這個值是不會增加)
# Opened_files的值(65+1)加1(需要打開.frm文件,緩存后,就關閉)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_files | 19 | +0
| Opened_files | 66 | +1
+---------------+-------+
2 rows in set (0.00 sec)
mysql> show open tables from test;
+----------+-------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+-------+--------+-------------+
| test | t0001 | 0 | 0 |
+----------+-------+--------+-------------+
1 row in set (0.00 sec)
mysql> show create table t0001\G
*************************** 1. row ***************************
Table: t0001
Create Table: CREATE TABLE `t0001` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/test/
mysqld 14683 mysql 33uW REG 253,1 98304 87851074 /home/mysql/mysql-5.1.47/data/test/t0001.ibd
2.2.2
對於innodb存儲引擎,table cache對其影響其實不是很大,innodb有自己的數據字典,可以緩存相關表信息。
PS:
看完上面的知識點之后,也可以繼續看 http://www.cnblogs.com/zuoxingyu/archive/2012/10/17/2727843.html 這篇關於物理刪除文件(MYISAM)的恢復方法。