高並發下MySQL出現checking permissions


 在某些數據訪問層框架中,會使用show full tables from test like 'demo',來檢查數據庫的狀態。當數據庫中表的數量較少時,並沒有出現嚴重的問題。但是當數據庫中的表數量多余千個時,且並發數較高時,通過show processlist就會發現show full tables語句絕大部分處於checking permissions狀態

| 2 | test | 192.168.15.128:57656 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 3 | test | 192.168.15.128:57657 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 4 | test | 192.168.15.128:57658 | NULL | Sleep | 0 | | NULL |
| 5 | test | 192.168.15.128:57659 | NULL | Query | 0 | Sending to client | show full tables from test like '%demo%' |
| 6 | test | 192.168.15.128:57662 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 7 | test | 192.168.15.128:57661 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 8 | test | 192.168.15.128:57660 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 9 | test | 192.168.15.128:57663 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 10 | test | 192.168.15.128:57664 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 11 | test | 192.168.15.128:57665 | NULL | Query | 0 | checking permissions | show full tables from test like '%demo%' |
| 12 | test | 192.168.15.128:57666 | test | Query | 0 | starting | show processlist |

從給出的狀態信息來看,很多人會誤以為這是在該SQL需要做復雜的權限檢查。google一下之后,發現也有人遇到類似的問題,並認為是mysql.user表中的條目數過多。但是我本機中,顯然不是這個原因。

mysql> select count(*) from mysql.user;
+----------+
| count(*) |
+----------+
| 5           |
+----------+
1 row in set (0.00 sec)

由於show full tables from test like '%demo%'需要檢查test數據庫下的所有frm文件,因此表的數量越多,就越有可能出現這個問題。為了驗證,我在兩個實例上分別創建一個表和創建2000個表

一個表時,


mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show full tables from test like 'demo';
+-----------------------+------------+
| Tables_in_test (demo) | Table_type |
+-----------------------+------------+
| demo | BASE TABLE |
+-----------------------+------------+
1 row in set (0.00 sec)

mysql> show profile;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000227 |
| checking permissions | 0.000020 |
| checking permissions | 0.000023 |
| Opening tables | 0.000452 |
| init | 0.000078 |
| System lock | 0.000051 |
| optimizing | 0.000030 |
| statistics | 0.000179 |
| preparing | 0.000134 |
| executing | 0.000069 |
| checking permissions | 0.000557 |
| Sending data | 0.000136 |
| end | 0.000036 |
| query end | 0.000032 |
| closing tables | 0.000042 |
| removing tmp table | 0.000110 |
| closing tables | 0.000060 |
| freeing items | 0.000122 |
| cleaning up | 0.000028 |
+----------------------+----------+
19 rows in set, 1 warning (0.01 sec)

 

2000個表時

mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show full tables from test like 'demo';
+-----------------------+------------+
| Tables_in_test (demo) | Table_type |
+-----------------------+------------+
| demo | BASE TABLE |
+-----------------------+------------+
1 row in set (0.01 sec)

mysql> show profile;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000083 |
| checking permissions | 0.000004 |
| checking permissions | 0.000002 |
| Opening tables | 0.000032 |
| init | 0.000008 |
| System lock | 0.000005 |
| optimizing | 0.000003 |
| statistics | 0.000104 |
| preparing | 0.000024 |
| executing | 0.000004 |
| checking permissions | 0.002991 |
| Sending data | 0.000014 |
| end | 0.000003 |
| query end | 0.000005 |
| closing tables | 0.000002 |
| removing tmp table | 0.000003 |
| closing tables | 0.000002 |
| freeing items | 0.000047 |
| cleaning up | 0.000013 |
+----------------------+----------+
19 rows in set, 1 warning (0.01 sec)

 

0.002991/0.000557=5.36,其所消耗時間增長了5倍以上,在高並發下,其現象更明顯。

那么標注為紅色的checking permission是否真正表示在做權限檢查了,答案是否定的。

通過檢查MySQL5.6源碼,可以發現,在執行show full tables from test like '%demo%'時,checking permission期間其實做了兩部分工作,

1、檢查權限

2、遍歷test數據庫下所有的frm文件,並獲取相關信息。根據獲得的信息,經過like條件過濾后,寫入到一個臨時表(memory引擎表)中

在sending data階段,從這個臨時表,把數據發送給用戶

因此在某些SQL語句下,狀態為checking permission時,並不一定真的在做權限檢查。 

所以不要頻繁的向數據庫發送show full tables from test like '%demo%',尤其是在表的數量很多時。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM