1 ########### suite/funcs_1/datadict/processlist_val.inc #########################
3 # Testing of values within INFORMATION_SCHEMA.PROCESSLIST #
5 # Ensure that the values fit to the current state of the connection and #
6 # especially that they change if a connection does nothing or runs some SQL. #
9 # - change the default database #
10 # - send some period of time no SQL command to the server #
11 # - send a long running query #
14 # 1. Please inform me if this test fails because of timing problems. #
15 # 2. Storage engine variants of this test do not make sense. #
16 # - I_S tables use the MEMORY storage engine whenever possible. #
17 # - There are some I_S tables which need column data types which are not #
18 # supported by MEMORY. Example: LONGTEXT/BLOB #
19 # MyISAM will be used for such tables. #
20 # The column PROCESSLIST.INFO is of data type LONGTEXT ----> MyISAM #
21 # - There is no impact of the GLOBAL(server) or SESSION default storage #
22 # engine setting on the engine used for I_S tables. #
23 # That means we cannot get NDB or InnoDB instead. #
24 # 3. The SHOW (FULL) PROCESSLIST command are for comparison. #
25 # The main test target is INFORMATION_SCHEMA.PROCESSLIST ! #
27 # The values of the PROCESSLIST columns HOST and TIME tend to cause #
28 # problems and therefore their printing has to be suppressed. #
29 # Examples of the exact values: #
30 # HOST: 'localhost' (UNIX derivates) #
31 # 'localhost:<varying_port>' (WINDOWS) #
32 # TIME: In many cases within this test 0 seconds but if the testing box is #
33 # overloaded we might get up to 2 seconds. #
35 # --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME> #
36 # 5. How to debug the script? #
37 # <graphical diff tool> \ #
38 # suite/funcs_1/datadict/processlist_val.inc \ #
39 # <Result|Reject|Log file> #
40 # I tweaked a lot of the script lines around "echo" so that you will get a #
41 # lot of useful synchronisation. #
44 # 2007-08-09 mleich Implement this test as part of #
45 # WL#3982 Test information_schema.processlist #
47 # Last Modification: #
48 # 2008-07-04 mleich Fix for #
49 # Bug#37853 Test "funcs_1.processlist_val_ps" fails in #
51 # - issues with printing of port (Win only) #
52 # - too optimistic assumptions about timing #
53 # + corrections of logic in poll routines #
54 # + minor improvements #
55 ################################################################################
58 --error 0, ER_CANNOT_USER
59 DROP USER test_user@
'localhost';
60 CREATE USER test_user@
'localhost';
61 GRANT ALL ON *.* TO test_user@
'localhost';
62 REVOKE PROCESS ON *.* FROM test_user@
'localhost';
63 SET PASSWORD FOR test_user@
'localhost' = PASSWORD(
'ddictpass');
72 # Show the definition of the PROCESSLIST table
73 #--------------------------------------------------------------------------
75 SHOW CREATE
TABLE INFORMATION_SCHEMA.PROCESSLIST;
78 # Ensure that the information about the own connection is correct.
79 #--------------------------------------------------------------------------
83 # - HOST (printed value is unified), the exact values are often like
85 # WIN: 'localhost:<some port>'
87 # - Command IN (no protocol -> 'Query', ps-protocol -> 'Execute')
88 # - TIME (printed value will be unified), the exact values are like
89 # "normal" load: 0 (seconds)
90 # "heavy" load: 1 or more (seconds)
92 # - INFO must contain the corresponding SHOW/SELECT PROCESSLIST
94 # 1. Just dump what we get
95 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
97 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
98 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
100 SHOW FULL PROCESSLIST;
102 # Determine the connection id of the current connection (default)
103 SET @default_id = CONNECTION_ID();
105 # 2. There must be exact one connection with @default_id;
106 SELECT COUNT(*) = 1 AS
"Expect exact one connection with this id"
107 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @default_id;
109 # 3. Check the remaining stuff
110 SELECT COUNT(*) = 1 AS
"Expect 1"
111 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @default_id
112 AND USER =
'root' AND DB =
'test' AND Command IN(
'Query',
'Execute')
113 AND State = 'executing';
116 USE information_schema;
117 SELECT COUNT(*) = 1 AS
"Is the DB correct?"
118 FROM INFORMATION_SCHEMA.PROCESSLIST
119 WHERE ID = @default_id AND DB =
'information_schema';
121 # 5. Change the statement
123 SELECT @my_info := INFO FROM INFORMATION_SCHEMA.PROCESSLIST
124 WHERE ID = @default_id;
127 SELECT @my_info =
'$my_statement'
128 AS
'Is the content of PROCESSLIST.INFO correct?';
130 # 6. TIME must have a reasonable value
131 SELECT COUNT(*) = 1 AS
"Has TIME a reasonable value?"
132 FROM INFORMATION_SCHEMA.PROCESSLIST
133 WHERE ID = @default_id AND 0 <= TIME < 10;
137 # Ensure that the information about an inactive connection is correct.
138 #--------------------------------------------------------------------------
141 # ----- establish connection con1 (user = test_user) -----
143 connect (con1,localhost,test_user,ddictpass,information_schema);
146 # ----- switch to connection default (user = root) -----
149 # We have now a second connection.
150 # First working phase for the new connection is with Command = 'Connect'.
151 # This is a very short phase and the likelihood to meet it is
152 # - nearly zero on average boxes with low parallel load
153 # - around some percent on weak or overloaded boxes
154 # (Bug#32153 Status output differs - scheduling ?)
155 # Therefore we do not try to catch this state.
156 # We poll till we reach the long lasting phase with Command = 'Sleep'.
157 # - USER = 'test_user'
158 # - DB = 'information_schema'
159 # - Command = 'Sleep'
163 # Poll till the connection con1 is in state COMMAND = 'Sleep'.
165 let $wait_timeout= 10;
166 let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
167 WHERE COMMAND =
'Sleep' AND USER =
'test_user';
168 --source include/wait_condition.inc
169 # 1. Just dump what we get
170 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
172 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
173 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
175 SHOW FULL PROCESSLIST;
177 # Pull ID and TIME of the second connection
178 SELECT ID,TIME INTO @test_user_con1_id,@time FROM INFORMATION_SCHEMA.PROCESSLIST
179 WHERE COMMAND =
'Sleep' AND USER =
'test_user';
181 # 2. The second connection must (behaviour at least since 2007) have an
182 # ID = ID_of_previous_connection + 1
183 SELECT @test_user_con1_id = @default_id + 1
184 AS
"Did we got the next higher PROCESSLIST ID?";
186 # 3. TIME must have a reasonable value
187 SELECT 0 <= @time < 10 AS
"Has TIME a reasonable value?";
189 # 4. HOST must be for both connections similar (varying port on Win)
190 SELECT COUNT(*) = 2 AS
"Is HOST LIKE 'localhost%'?"
191 FROM INFORMATION_SCHEMA.PROCESSLIST
192 WHERE HOST LIKE
'localhost%';
194 # 5. Check the remaining stuff
195 SELECT COUNT(*) = 1 AS
"Expect 1"
196 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @test_user_con1_id
197 AND USER =
'test_user' AND DB =
'information_schema'
198 AND Command =
'Sleep' AND State =
'' AND INFO IS NULL;
200 # 6. Check that TIME increases
201 let $wait_timeout= 10;
202 let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
203 WHERE COMMAND =
'Sleep' AND USER =
'test_user'
205 --source include/wait_condition.inc
209 # Ensure that the user test_user sees only connections with his username
210 # because he has not the PROCESS privilege.
211 #----------------------------------------------------------------------------
214 # ----- switch to connection con1 (user = test_user) -----
217 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
219 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
220 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
222 SHOW FULL PROCESSLIST;
226 # Ensure that the user test_user sees all connections with his username.
227 #----------------------------------------------------------------------------
230 ----- establish connection con2 (user = test_user) ------
232 connect (con2,localhost,test_user,ddictpass,information_schema);
234 # ----- switch to connection default (user = root) -----
237 # If the testing box is under heavy load we might see within some of the
238 # next queries connection
239 # con2 with Command = 'Connect'
240 # con1 with INFO = 'SHOW FULL PROCESSLIST' and STATE = 'Writing to net'
241 # Both phases are too short to be checked.
243 # Poll till all connections of 'test_user' are in a state with COMMAND = 'Sleep'
245 let $wait_condition= SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST
246 WHERE USER =
'test_user' AND COMMAND =
'Sleep';
247 --source include/wait_condition.inc
249 # ----- switch to connection con2 (user = test_user) -----
252 # Just dump what we get
253 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
255 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
256 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
258 SHOW FULL PROCESSLIST;
261 # ----- switch to connection default (user = root) -----
264 # Pull the ID of con2, we will need it later
265 SELECT ID INTO @test_user_con2_id FROM INFORMATION_SCHEMA.PROCESSLIST
266 WHERE ID <> @test_user_con1_id
267 AND USER =
'test_user' AND DB =
'information_schema';
271 # Ensure we get correct information about a connection during work
272 #----------------------------------------------------------------------------
275 # ----- switch to connection con2 (user = test_user) -----
278 # "Organise" a long running command to be observed by the root user.
280 # Send a long enough running statement to the server, but do not
281 # wait till the result comes back.
283 # Worst case scenario (=high I/O load on testing box):
285 # Up to 2 seconds runtime per SELECT ... FROM INFORMATION_SCHEMA.PROCESSLIST
287 # - The following sequence contains ~ 4 of such SELECTs
288 # Therefore we sleep 10 seconds.
290 SELECT sleep(10), 17;
295 # ----- switch to connection default (user = root) -----
299 # Poll till connection con2 is in state 'User sleep'.
301 # Expect to see within the processlist the other connection just during
302 # statement execution.
303 # - USER = 'test_user'
304 # - DB = 'information_schema'
305 # - Command = 'Query'(run without --ps-protocol)/'Execute' (run --ps-protocol)
307 # - State = 'User sleep'
308 # - INFO = $sleep_command
310 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
311 WHERE ID = @test_user_con2_id AND Command IN('Query','Execute')
312 AND State = 'User sleep' AND INFO IS NOT NULL ;
313 --source include/wait_condition.inc
314 # 1. Just dump what we get
315 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
317 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
318 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
320 SHOW FULL PROCESSLIST;
322 # Pull some information about the connection con2
323 SELECT STATE, TIME, INFO INTO @state, @time, @info
324 FROM INFORMATION_SCHEMA.PROCESSLIST
325 WHERE ID = @test_user_con2_id;
326 # 2. TIME must have a reasonable value
327 SELECT 0 <= @time < 10 AS
"Has TIME a reasonable value?";
328 # 3. STATE must be 'User sleep'
329 SELECT @state =
'User sleep' AS
"Has STATE the expected value?";
331 eval SELECT @info =
'$sleep_command' AS
"Has INFO the expected value?";
332 # 5. Check that TIME increases
333 let $wait_timeout= 10;
334 let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
335 WHERE ID = @test_user_con2_id AND INFO IS NOT NULL AND TIME > @time;
336 --source include/wait_condition.inc
338 # ----- switch to connection con2 (user = testuser) -----
342 # Pull("reap") the result set from the statement executed with "send".
346 # ----- switch to connection default (user = root) -----
350 # Poll till all connections of 'test_user' are in a state with COMMAND = 'Sleep'
352 let $wait_timeout= 10;
353 let $wait_condition= SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST
354 WHERE COMMAND =
'Sleep' AND USER =
'test_user';
355 --source include/wait_condition.inc
359 # Ensure that we see that a connection "hangs" when colliding with a
361 #----------------------------------------------------------------------------
363 LOCK
TABLE test.t1 WRITE;
366 # ----- switch to connection con2 (user = test_user) -----
370 # Send a statement to the server, but do not wait till the result
371 # comes back. We will pull this later.
374 SELECT COUNT(*) FROM test.t1;
376 # ----- switch to connection default (user = root) -----
380 # Poll till INFO is no more NULL and State = 'Waiting for table metadata lock'.
382 let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
383 WHERE INFO IS NOT NULL AND STATE = 'Waiting for
table metadata lock';
384 --source include/wait_condition.inc
386 # Expect to see the state 'Waiting for table metadata lock' for the third
387 # connection because the SELECT collides with the WRITE TABLE LOCK.
388 --replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
390 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
394 # ----- switch to connection con2 (user = test_user) -----
398 # Pull("reap") the result set from the statement executed with "send".
404 # Ensure that SHOW/SELECT processlist can handle extreme long commands
405 #----------------------------------------------------------------------------
407 # We do not want to waste runtime, therefore we run the following test based
408 # on "Lock collision" and not with some "sleep(10)".
410 # ----- switch to connection default (user = root) -----
413 LOCK
TABLE test.t1 WRITE;
416 # ----- switch to connection con2 (user = test_user) -----
420 # Send a long (~20 KB code) statement to the server, but do not wait
421 # till the result comes back. We will pull this later.
424 `SELECT CONCAT(
'BEGIN-',
425 REPEAT(
'This is the representative of a very long statement.',400),
428 SELECT count(*),
'$string' AS
"Long string" FROM test.t1;
432 # ----- switch to connection default (user = root) -----
436 # Poll till INFO is no more NULL and State = 'Waiting for table metadata lock'.
438 let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
439 WHERE INFO IS NOT NULL AND STATE = 'Waiting for
table metadata lock';
440 --source include/wait_condition.inc
443 # Statement Content of INFO
444 # SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST Complete statement
445 # SHOW FULL PROCESSLIST Complete statement
446 # SHOW PROCESSLIST statement truncated after 100 char
448 --replace_column 1 <ID> 3 <HOST_NAME> 5 <COMMAND> 6 <TIME> 7 <STATE>
450 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
451 --replace_column 1 <ID> 3 <HOST_NAME> 5 <COMMAND> 6 <TIME> 7 <STATE>
453 SHOW FULL PROCESSLIST;
454 --replace_column 1 <ID> 3 <HOST_NAME> 5 <COMMAND> 6 <TIME> 7 <STATE>
459 # ----- switch to connection con2 (user = test_user) -----
463 # Pull("reap") the result set from the monster statement executed with "send".
470 # ----- switch to connection default (user = root) -----
474 ----- disconnect con1 and con2 -----
478 DROP USER test_user@
'localhost';