1. 程式人生 > >讓天下沒有難用的資料庫 » 注意table_open_cache過小也會導致效能問題

讓天下沒有難用的資料庫 » 注意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調大即可解決目前的問題:table_open_cache1tips:

通常在設定table_open_cache引數的時候,在業務的高峰時期,檢查open_Tables的值,如果open_Tables的值與table_open_cache的值相等,並且opened_tales的值在不斷的增加,這個時候就需要對table_open_cache的值增加了,這個時候執行緒的狀態:Opening tables。目前rds table_open_cache的初始值已經調大至2000。