`
丁林.tb
  • 浏览: 795014 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

与MySQL的注释、Query_cache有关的一个bug

阅读更多

今天有同学问了一个关于注释的问题,顺藤摸瓜发现一个bug,简要说明下。

有关注释的一些QA

Q MySQL注释有哪些格式

AMySQL的注释格式有三种,分别是 /**/ -- #。具体参见手册

        

Q:在一些导出文件中见过/*! xxx*/,是不是注释?

A:  需要注意的是/*! */ 这种格式,对于MySQL来说不是注释,是能够直接执行的。同时这个格式还支持指定版本号,比如/*!50518 xxxx*/ 表示,若server端版本大于5518,则后续的xxxx作为语句的一部分执行,否则忽略。

 

Q:语句中的注释会不会发给server

A:默认是不会的。一种方法是在mysql连接中加-c (--comments)参数,则会强制将注释部分也发给Server端。 另一种方法与上一条答案有关,指定一个超过server端的版本号。如果比如指定 /*!121221 xxxx*/,也可以发给server

 

Q: 慢查询日志会不会记录注释部分

A: 慢查询会记录语句原文,如果用上面说到的两种方法将注释发给server,若记录到慢查询日志中,就会显示。(也许可以用这种方法来加入语句来源,做业务慢查询分析)

   不只是慢查询,如果使用statement格式的binlog,注释部分也会写入到binlog中。

 

Q: 使用注释的语句能不能使用Query_cache(QC)

A:可以的,QC 会用原文作key,因此若有注释,则注释部分也要求一模一样才会命中QC

 

Query_cache小背景

QC是一个hash表,key是语句原文,value是查询结果。因此要求一模一样的语句才会命中。

 

Bug描述

若你的语句中是这么写select * from t /*!121221 just test*/. 按照上面说到的,这个语句是会被全文发到server端,不用怕语法错误,因为121221这个版本号大于现有的所有可用版本。因此实际执行的是select * from t;

 

如果query_cache正常打开,会看到第一次执行后show status like 'qcache_inserts';值确实+1.

然后再次执行,发现Qcache_hits并没有+1,反而是Qcache_not_cached +1.

说明这个语句虽然被插入QC中,但是却用不上

 

Bug分析

如果这个查询是慢查询,我们可以在慢查询日志中看到,它记录的是 select * from t /* 121221 just test*/ ‘!’被换成了空格。

这个替换是在解析阶段发生的。

这样就有问题了:

1、  判断QC是否命中是在解析之前,也就是SQL的原文

2、  第一次执行不命中QC,需要执行,执行期间将!替换成空格

3、  结果在插入QC中,但是此时的key,已经是替换过的。

4、  下一次执行使用的仍然是带!的,因此仍然无法命中

 

    一种解决方法

PerconaMariaDB(5.5+)中有一个特性,刚好绕过这个问题。

参数query_cache_strip_comments用于控制QC中是否去掉SQL语句的注释部分。默认是OFF,若打开,插入QC中的是原语句,可以解决这个问题。

 

'!'为什么要替换

这个问题的是由解析器将/*! */替换成/*  */ 造成的。在5.1其实没有这个替换行为(感谢@飞哥最爱白菜 指出)。为什么MySQL要加上这个动作呢?

原因是我们上面提到的,binlog中会记录语句原文,包括/*!VERSION xxx*/的内容。

这样在主从同步时,若VERSION大于主库版本而小于从库版本(官方是承诺向下兼容的),则可能会出现主从执行不一致的问题。

主库发现xxx不会被执行,就做了替换,语句变成 /* VERSION xxx*/,这是个标准的注释,从库也不会执行xxx部分。

因此属于解决bug的时候引入的。

2
1
分享到:
评论
2 楼 lidayu_up 2013-04-11  
虽然dump出来时间不一样,但是导进去的时候,又变回来了
1 楼 zhoujy 2012-12-18  
好文,学习了。

相关推荐

    Mycat处理连接数据库8.0以上程序报错query_cache_size

    这个版本应该能够更好地处理与MySQL 8.0的兼容性,避免因query_cache_size问题导致的连接错误。 为了解决“query_cache_size”报错,你可以按照以下步骤操作: 1. **升级Mycat**:确保你的Mycat服务器版本至少为...

    解决mycatJDBC8驱动连接Mycat1.6报错 Unknown system variable 'query_cache_size'

    这个问题出现的原因在于MySQL 8.0版本中移除了`query_cache`相关的系统变量和功能,因此在使用新版本的JDBC驱动去连接旧版Mycat(可能基于较早版本的MySQL)时,会因找不到这个变量而抛出错误。 首先,我们需要理解...

    MySQL高速缓存启动方法及参数详解(query_cache_size)

    要启用查询缓存,你需要在MySQL的配置文件(通常是`my.ini`或`my.cnf`)中设置`query_cache_size`参数为一个非零值,这个值表示缓存的大小,单位是字节。通常建议设置为1024的倍数,例如32MB。这样,系统将为查询...

    对于mysql的query_cache认识的误区

    如果空格是加在query之前,比如是在query的起始处加了空格,这样是丝毫不影响query cache的结果的,mysql认为这是一条query, 而如果空格是在query中,那会影响query cache的结果,mysql会认为是不同的query

    Mysql优化调优中两个重要参数table_cache和key_buffer

    当Mysql访问一个表时,如果在Mysql表缓冲区中还有空间,那么这个表就被打开并放入表缓冲区,这样做的好处是可以更快速地访问表中的内容。一般来说,可以通过查看数据库运行峰值时间的状态值Open_tables和Opened_...

    php提示Warning:mysql_fetch_array() expects的解决方法

    在mysql数据库连接时碰到Warning: mysql_fetch_array() expects …错误提示,根据我的经验这个是sql返回的query为空了,我们没有加己判断直接使用了. mysql_fetch_array()函数导致的,下面我们一起来看问题解决方案,我...

    mysql.rar_c mysql_c++ mysql_mysql c_window mysql

    在Windows环境下,使用C语言与MySQL数据库进行交互是一项常见的任务,尤其对于开发跨平台应用程序的开发者来说。在本文中,我们将深入探讨如何在Windows操作系统上通过C语言连接、操作MySQL数据库,以及涉及到的相关...

    MYSQL_C_API.rar_MYSQL_mysql c++

    这个“MYSQL_C_API.rar_MYSQL_mysql c++”压缩包文件包含了一个详细注释版的MySQL C API文档,名为“MYSQL_C_API详解.doc”,对于开发者来说,是一个非常实用的参考资料。 MySQL C API允许程序员通过编写C或C++代码...

    mysql.rar_MySQL Visual C++_MySql查询_c语言mysql_mysql c语言_mysql操作

    Visual C++环境下,你可以利用面向对象编程特性,创建一个MySQL数据库操作的类,将每个数据库操作作为类的方法。 总的来说,C语言与MySQL的结合提供了强大的数据库操作能力。通过学习和理解上述知识点,你将能够...

    mysql_test_c__by_wy.rar_MYSQL_mysql api_mysql c++

    MySQL是世界上最受欢迎的关系型数据库管理系统之一,而MySQL C API 是MySQL提供的一种用于在C或C++编程语言中与MySQL服务器进行交互的接口。本示例"mysql_test_c__by_wy.rar"旨在演示如何利用MySQL C API进行基本的...

    MySQL性能优化之table_cache配置参数浅析

    由于每个客户端连接都会至少访问一个表,因此此参数的值与max_connections有关。 缓存机制 当某一连接访问一个表时,MySQL会检查当前已缓存表的数量。如果该表已经在缓存中打开,则会直接访问缓存中的表已加快查询...

    mysql-query-browser-1.1.18.tar.gz_mysql browser_mysql query brow

    MySQL Query Browser 1.1.18 是一个专为MySQL数据库设计的图形化查询工具,它为用户提供了直观且功能丰富的界面,以便于管理和查询数据库。这个软件版本1.1.18是开源的,意味着它的源代码是公开的,允许用户自由地...

    mysql_lib.rar_C MYSQL_MYSQL_c mysql_mysql.l_vc++和MySQL

    在本文中,我们将详细探讨MySQL与VC++的集成以及相关知识点。 首先,`mysql.h`是MySQL C API的头文件,它提供了所有必要的函数声明和数据结构定义,用于编写连接和操作MySQL数据库的应用程序。开发者可以通过包含这...

    linux_mysql.rar_c mysql linux_linux mysql_linux mysql_linux m

    这个API包含了一系列的函数,如mysql_init()用于初始化一个连接结构体,mysql_real_connect()用于建立到服务器的连接,mysql_query()用于执行SQL查询,以及mysql_store_result()和mysql_fetch_row()用于处理查询结果...

    mysql_include.rar_mysql include_mysql_include_mysql_time.h_mysql

    1. `mysql_time.h`:这个头文件提供了关于时间、日期和时间戳的结构体和函数,用于处理与MySQL数据库中的日期和时间数据类型相关的操作。其中最重要的结构体是`MYSQL_TIME`,它包含年、月、日、小时、分钟、秒等信息...

    MySQL性能优化配置参数之thread_cache和table_cache详解

    本文将深入探讨两个重要的性能优化配置参数:thread_cache和table_cache,它们分别与连接管理和表缓存密切相关。 首先,我们来理解thread_cache。thread_cache,即连接池,是MySQL用来提高客户端请求创建连接效率的...

    Mysql.rar_C MYSQL_C++ 访问 mysql_c# mysql_c++ mysql_mysql c++

    MySQL是一款广泛使用的开源关系型数据库管理系统,其C++接口提供了与数据库交互的能力。在本压缩包文件中,我们看到的是关于使用C++通过Connector/C++库来访问MySQL数据库的相关代码。接下来,我们将深入探讨这个...

Global site tag (gtag.js) - Google Analytics