讓天下沒有難用的資料庫 » 注意table_open_cache過小也會導致效能問題
週一的時候有一個客戶反饋自從上次rds重啟後,慢查詢特別多,有大量響應時間在1~3秒的請求,後端的工程師介入調查,發現隨便建一個最簡單的表,插入資料都需要300ms。一開始的時候懷疑可能是網路延遲導致的,客戶測試了從ecs到rds的網路延遲,測試結果網路延時不到1ms,那問題到底出現在那裡?在MySQL中可以使用profile去檢視SQL的執行時間主要消耗在哪裡,所以我們來看一下profile:
mysql> show profiles;
+———-+————+—————–+
| Query_ID | Duration | Query |
+———-+————+—————–+
| 1 | 0.09211525 | select * from d |
| 2 | 0.03659925 | select * from d |
| 3 | 0.22665400 | select * from d |
| 4 | 0.11063350 | select * from d |
| 5 | 0.06929725 | select * from d |
| 6 | 0.09054975 | select * from d |
| 7 | 0.15971375 | select * from d |
| 8 | 0.12960625 | select * from d |
| 9 | 0.22713975 | select * from d |
| 10 | 0.00124025 | select * from d |
+———-+————+—————–+
mysql> show profile cpu for query 4;
+———————-+———-+———-+————+
| Status | Duration | CPU_user | CPU_system |
+———————-+———-+———-+————+
| starting | 0.000198 | 0.001000 | 0.000000 |
| checking permissions | 0.000053 | 0.000000 | 0.000000 |
| Opening tables | 0.000454 | 0.000999 | 0.001000 |
| init | 0.000059 | 0.000000 | 0.000999 |
| System lock | 0.000055 | 0.000000 | 0.000000 |
| optimizing | 0.000053 | 0.000000 | 0.000000 |
| statistics | 0.000056 | 0.000000 | 0.000000 |
| preparing | 0.000056 | 0.000000 | 0.000000 |
| executing | 0.000052 | 0.001000 | 0.000000 |
| Sending data | 0.000072 | 0.000000 | 0.000000 |
| end | 0.000053 | 0.000000 | 0.000000 |
| query end | 0.000056 | 0.000000 | 0.000000 |
| closing tables | 0.000056 | 0.000000 | 0.000000 |
| freeing items | 0.000076 | 0.000000 | 0.000000 |
| cleaning up | 0.000056 | 0.000000 | 0.000000 |
+———————-+———-+———-+————+
mysql> show profile cpu for query 5;
+———————-+———-+———-+————+
| Status | Duration | CPU_user | CPU_system |
+———————-+———-+———-+————+
| starting | 0.000201 | 0.000000 | 0.000000 |
| checking permissions | 0.000054 | 0.000000 | 0.000000 |
| Opening tables | 0.127694 | 0.116982 | 0.009999 |
| init | 0.000101 | 0.000000 | 0.000999 |
| System lock | 0.000054 | 0.000000 | 0.000000 |
| optimizing | 0.000052 | 0.000000 | 0.000000 |
| statistics | 0.000056 | 0.000000 | 0.000000 |
| preparing | 0.000056 | 0.001000 | 0.000000 |
| executing | 0.000052 | 0.000000 | 0.000000 |
| Sending data | 0.000072 | 0.000000 | 0.000000 |
| end | 0.000053 | 0.000000 | 0.000000 |
| query end | 0.000053 | 0.000000 | 0.000000 |
| closing tables | 0.009045 | 0.008998 | 0.002000 |
| freeing items | 0.000076 | 0.001000 | 0.000000 |
| cleaning up | 0.000058 | 0.000000 | 0.000000 |
+———————-+———-+———-+————+
15 rows in set, 1 warning (0.00 sec)
mysql> show profile cpu for query 6;
+———————-+———-+———-+————+
| Status | Duration | CPU_user | CPU_system |
+———————-+———-+———-+————+
| starting | 0.000197 | 0.001000 | 0.000000 |
| checking permissions | 0.000053 | 0.000000 | 0.000000 |
| Opening tables | 0.013475 | 0.014998 | 0.000000 |
| init | 0.000060 | 0.000000 | 0.000000 |
| System lock | 0.000067 | 0.000000 | 0.000000 |
| optimizing | 0.000059 | 0.000000 | 0.002000 |
| statistics | 0.000061 | 0.000000 | 0.000000 |
| preparing | 0.000059 | 0.000000 | 0.000000 |
| executing | 0.000053 | 0.000000 | 0.000000 |
| Sending data | 0.000073 | 0.000000 | 0.000000 |
| end | 0.000054 | 0.000000 | 0.000000 |
| query end | 0.000055 | 0.000000 | 0.000000 |
| closing tables | 0.000967 | 0.000000 | 0.001000 |
| freeing items | 0.000077 | 0.000000 | 0.000000 |
| cleaning up | 0.000053 | 0.001000 | 0.000000 |
+———————-+———-+———-+————+
15 rows in set, 1 warning (0.00 sec)
通過這個profile可以看到執行時間主要花費在Opening tables,這個時候問題就比較清楚了,我們看一下table_open_cache這個引數的值是否較小,結果這個RDS的table_open_cache只有100,而這個RDS卻建立了上萬張的表,進而導致了每次訪問新的表的時候不得不重新開啟,所以只需把table_open_cache調大即可解決目前的問題:tips:
通常在設定table_open_cache引數的時候,在業務的高峰時期,檢查open_Tables的值,如果open_Tables的值與table_open_cache的值相等,並且opened_tales的值在不斷的增加,這個時候就需要對table_open_cache的值增加了,這個時候執行緒的狀態:Opening tables。目前rds table_open_cache的初始值已經調大至2000。