Bug #40986 Leading line comments prevent Query Cache from caching result.

Submitted: 24 Nov 2008 16:29 Modified: 7 Jul 2017 9:44
Reporter: David Walker Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Server: Query Cache Severity:S3 (Non-critical)
Version:4.1, 5.0, 5,1, 6.0 bzr OS:Any
Assigned to: CPU Architecture:Any
Tags: query cache comment

[24 Nov 2008 16:29] David Walker
Description:
SELECT statements with leading line comments (beginning with '#' or '--') are still not cached correctly by the Query Cache. 

'/* */'-style comments are fine and do not affect caching. See fix for bug#824, (which is only a partial fix)

Also, the manual page for comment syntax states that leading comments should no longer prevent the query cache from caching results in MySQL 5.0+, but this is only true for '/* */'-style comments, and should be corrected.

How to repeat:

Configure query cache.

mysql> show status like 'query_cache%';

    >>> sql_query = "-- my comment\nSELECT * FROM my_table LIMIT 1"
    >>> cursor.execute(sql_query)
    >>> cursor.execute(sql_query)
    >>> cursor.execute(sql_query)

mysql> show status like 'query_cache%';

Note that number of hits has not increased between "SHOW STATUS..." invocations. Remove the leading comment, and the hits will increase, as expected.

Suggested fix:
Finish the fix to bug#824: also do a cache lookup when '-' and '#' are encountered as the first non-whitespace character in the query text.
[24 Nov 2008 16:32] David Walker
Sorry, the manual page I was trying to refer to was:
http://dev.mysql.com/doc/refman/5.0/en/query-cache-how.html
(Not the comment syntax page.)
[4 Apr 2009 20:42] Sveta Smirnova
Thank you for the report.

Verified as described.

PHP test case:

<?
$mysqli = mysqli_connect('127.0.0.1', 'root', '', 'test', 4040);
mysqli_multi_query($mysqli, '
	flush status;
	drop table if exists t1;
	create table t1(id int);
	insert into t1 values(1),(2),(3),(3),(4),(5);
	insert into t1 select * from t1;
	insert into t1 select * from t1;
	insert into t1 select * from t1;
	insert into t1 select * from t1;');

do { if ($res = $mysqli->store_result()) { $res->free(); } } while ($mysqli->next_result());

echo "show status like 'Qcache%':\n";
var_dump(mysqli_error($mysqli));
mysqli_multi_query($mysqli, "show status like 'Qcache%'");
do {
		if ($res = $mysqli->store_result()) {
			while ($row = mysqli_fetch_array($res)) echo $row[0] . ': ' . $row[1] . "\n";
				$res->free();
		}
}while ($mysqli->next_result());

//$query = "select * from t1";
$query="--comment\nselect * from t1";
mysqli_multi_query($mysqli, $query);
do { if ($res = $mysqli->store_result()) { $res->free(); } } while ($mysqli->next_result());
mysqli_multi_query($mysqli, $query);
do { if ($res = $mysqli->store_result()) { $res->free(); } } while ($mysqli->next_result());
mysqli_multi_query($mysqli, $query);
do { if ($res = $mysqli->store_result()) { $res->free(); } } while ($mysqli->next_result());

echo "Error: " . mysqli_error($mysqli) . "\n";

mysqli_multi_query($mysqli, "show status like 'Qcache%'");
echo "show status like 'Qcache%':\n";
do {
		if ($res = $mysqli->store_result()) {
			while ($row = mysqli_fetch_array($res)) echo $row[0] . ': ' . $row[1] . "\n";
						$res->free();
		}
}while ($mysqli->next_result());

?>
[12 May 2010 0:44] Justin Swanhart
It is a problem with 5.1.45 with non-static comments, even with /* */ comments.  I made a PHP test case:

<?php

$conn = mysql_connect('127.0.0.1','root','',true) or die(mysql_error() . "\n");

function get_counters() {
$com_select=0;
$qcache_hits=0;
  global $conn;
  $stmt = mysql_query("show global status where Variable_name in( 'com_select', 'Qcache_hits' )", $conn) or die(mysql_error() ."\n");
  while($row = mysql_fetch_assoc($stmt)) {
  #print_r($row);
    if($row['Variable_name'] == 'Com_select') $com_select = $row['Value'];
    if($row['Variable_name'] == 'Qcache_hits') $qcache_hits = $row['Value'];
  }
  return array("cs" => $com_select, "qc" => $qcache_hits);
}

/* return 1 on qc hit, 0 on miss*/
function test_sql($sql) {
global $conn;
  $sql = sprintf($sql, mt_rand(1,10000));
  $old = get_counters();
  $stmt = mysql_query($sql, $conn);
  $new = get_counters();

  /* was it a miss? */
  if ($new['cs'] - $old['cs'] > 0) return 0;

  return 1; 
}

function testit($sql, $count=25) {
  // this will only change the query with %d in it..
  $hits = 0;
  for($i=0;$i<$count;++$i) {
    if(test_sql($sql) == 1) {
      ++$hits;
    }
  }

  echo "$sql\nTotal: $count\nHits: $hits\n";
}
  

$sql = "select c1 from test.t1 limit 1";
testit($sql);
$sql = " select c1 from test.t1 limit 1";
testit($sql);
$sql = "/* static comment*/select c1 from test.t1 limit 1";
testit($sql);
$sql = "/* changing comment %d*/select c1 from test.t1 limit 1";
testit($sql);
$sql = "/* changing query*/select c1 from test.t1 where c1 <= %d limit 1";
testit($sql);
$sql = "-- static comment\nselect c1 from test.t1 limit 1";
testit($sql);

 echo "\ndone\n";

----- OUTPUT -----

select c1 from test.t1 limit 1
Total: 25
Hits: 25
 select c1 from test.t1 limit 1
Total: 25
Hits: 25
/* static comment*/select c1 from test.t1 limit 1
Total: 25
Hits: 25
/* changing comment %d*/select c1 from test.t1 limit 1
Total: 25
Hits: 0
/* changing query*/select c1 from test.t1 where c1 <= %d limit 1
Total: 25
Hits: 0
-- static comment
select c1 from test.t1 limit 1
Total: 25
Hits: 0

done
[12 May 2010 0:52] Justin Swanhart
I do not think that this should be marked as a feature request.  This is clearly a bug with the query cache!
[6 Jul 2010 7:05] Valeriy Kravchuk
Bug #55016 was marked as a duplicate of this one.
[7 Jul 2017 9:44] Erlend Dahl
MySQL will no longer invest in the query cache, see:

http://mysqlserverteam.com/mysql-8-0-retiring-support-for-the-query-cache/

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.069 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.