今天有同学问了一个关于注释的问题,顺藤摸瓜发现一个bug,简要说明下。
有关注释的一些QA
Q: MySQL注释有哪些格式
A:MySQL的注释格式有三种,分别是 /**/ -- 和 #。具体参见手册
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、 下一次执行使用的仍然是带!的,因此仍然无法命中
一种解决方法
Percona和MariaDB(5.5+)中有一个特性,刚好绕过这个问题。
参数query_cache_strip_comments用于控制QC中是否去掉SQL语句的注释部分。默认是OFF,若打开,插入QC中的是原语句,可以解决这个问题。
'!'为什么要替换
这个问题的是由解析器将/*! */替换成/* */ 造成的。在5.1其实没有这个替换行为(感谢@飞哥最爱白菜 指出)。为什么MySQL要加上这个动作呢?
原因是我们上面提到的,binlog中会记录语句原文,包括/*!VERSION xxx*/的内容。
这样在主从同步时,若VERSION大于主库版本而小于从库版本(官方是承诺向下兼容的),则可能会出现主从执行不一致的问题。
主库发现xxx不会被执行,就做了替换,语句变成 /* VERSION xxx*/,这是个标准的注释,从库也不会执行xxx部分。
因此属于解决bug的时候引入的。
分享到:
相关推荐
这个版本应该能够更好地处理与MySQL 8.0的兼容性,避免因query_cache_size问题导致的连接错误。 为了解决“query_cache_size”报错,你可以按照以下步骤操作: 1. **升级Mycat**:确保你的Mycat服务器版本至少为...
这个问题出现的原因在于MySQL 8.0版本中移除了`query_cache`相关的系统变量和功能,因此在使用新版本的JDBC驱动去连接旧版Mycat(可能基于较早版本的MySQL)时,会因找不到这个变量而抛出错误。 首先,我们需要理解...
THREAD_CACHE MySQL里面为了提高客户端请求创建连接过程的性能,提供了一个连接池也就是 Thread_Cache池,将空闲的连接线程放在连接池中,而不是立即销毁.这样的好处就是,当又有一个新的请求的时候,mysql不会立即去创建...
要启用查询缓存,你需要在MySQL的配置文件(通常是`my.ini`或`my.cnf`)中设置`query_cache_size`参数为一个非零值,这个值表示缓存的大小,单位是字节。通常建议设置为1024的倍数,例如32MB。这样,系统将为查询...
如果空格是加在query之前,比如是在query的起始处加了空格,这样是丝毫不影响query cache的结果的,mysql认为这是一条query, 而如果空格是在query中,那会影响query cache的结果,mysql会认为是不同的query
当Mysql访问一个表时,如果在Mysql表缓冲区中还有空间,那么这个表就被打开并放入表缓冲区,这样做的好处是可以更快速地访问表中的内容。一般来说,可以通过查看数据库运行峰值时间的状态值Open_tables和Opened_...
在mysql数据库连接时碰到Warning: mysql_fetch_array() expects …错误提示,根据我的经验这个是sql返回的query为空了,我们没有加己判断直接使用了. mysql_fetch_array()函数导致的,下面我们一起来看问题解决方案,我...
在Windows环境下,使用C语言与MySQL数据库进行交互是一项常见的任务,尤其对于开发跨平台应用程序的开发者来说。在本文中,我们将深入探讨如何在Windows操作系统上通过C语言连接、操作MySQL数据库,以及涉及到的相关...
这个“MYSQL_C_API.rar_MYSQL_mysql c++”压缩包文件包含了一个详细注释版的MySQL C API文档,名为“MYSQL_C_API详解.doc”,对于开发者来说,是一个非常实用的参考资料。 MySQL C API允许程序员通过编写C或C++代码...
Visual C++环境下,你可以利用面向对象编程特性,创建一个MySQL数据库操作的类,将每个数据库操作作为类的方法。 总的来说,C语言与MySQL的结合提供了强大的数据库操作能力。通过学习和理解上述知识点,你将能够...
MySQL是世界上最受欢迎的关系型数据库管理系统之一,而MySQL C API 是MySQL提供的一种用于在C或C++编程语言中与MySQL服务器进行交互的接口。本示例"mysql_test_c__by_wy.rar"旨在演示如何利用MySQL C API进行基本的...
其中,"CMYSQL"和"_mysql"通常与MySQL C API有关,而"mysql_dev c++"和"mysql_c++"则暗示了可能有C++库或示例代码用于DevC++来实现MySQL的访问。 描述中的"成功使得dev连接mysql,成功使得dev连接mysql"重复强调了...
由于每个客户端连接都会至少访问一个表,因此此参数的值与max_connections有关。 缓存机制 当某一连接访问一个表时,MySQL会检查当前已缓存表的数量。如果该表已经在缓存中打开,则会直接访问缓存中的表已加快查询...
MySQL 5.6 中的 `table_open_cache` 参数是一个关键的性能调优选项,它直接影响着数据库系统的响应时间和资源利用率。`table_open_cache` 以前被称为 `table_cache`,自 5.1.3 版本起进行了更名。这个参数设定的是 ...
MySQL Query Browser 1.1.18 是一个专为MySQL数据库设计的图形化查询工具,它为用户提供了直观且功能丰富的界面,以便于管理和查询数据库。这个软件版本1.1.18是开源的,意味着它的源代码是公开的,允许用户自由地...
在本文中,我们将详细探讨MySQL与VC++的集成以及相关知识点。 首先,`mysql.h`是MySQL C API的头文件,它提供了所有必要的函数声明和数据结构定义,用于编写连接和操作MySQL数据库的应用程序。开发者可以通过包含这...
这个API包含了一系列的函数,如mysql_init()用于初始化一个连接结构体,mysql_real_connect()用于建立到服务器的连接,mysql_query()用于执行SQL查询,以及mysql_store_result()和mysql_fetch_row()用于处理查询结果...
1. `mysql_time.h`:这个头文件提供了关于时间、日期和时间戳的结构体和函数,用于处理与MySQL数据库中的日期和时间数据类型相关的操作。其中最重要的结构体是`MYSQL_TIME`,它包含年、月、日、小时、分钟、秒等信息...