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';