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');
65
DROP TABLE IF EXISTS test.t1;
67
CREATE TABLE test.t1 (f1 BIGINT);
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';