MySQL Server可执行注释
* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
- 前言
- 可执行注释
- 结语
前言
MySQL Server当前支持如下3种注释风格:
- 以'#'开头的单行注释
- 以'-- '开头的单行注释
- C语言风格的单行/多行注释
如下SQL脚本给出了3种注释风格的示例:
/* 这是一个
多行注释
示例
*/
select 1 from dual;
select 2 from dual; # 单行注释用例1
select 3 from dual; -- 单行注释用例2
可执行注释
为了支持在不同数据库之间的可移植性,MySQL Server针对C风格的注释在解析上做了一些扩展,当注释满足如下风格时,MySQL Server将会解析并执行注释中的代码:
/*! MySQL-specific code */
通过比较如下两个带注释的SQL语句的执行结果可以比较直观地看出可执行注释语句的行为:
# 普通注释,'+1' 被忽略
mysql> select 1 /* +1 */;
+---+
| 1 |
+---+
| 1 |
+---+
# 可执行注释,'+1' 被当成语句的一部分
mysql> select 1 /*! +1 */;
+-------+
| 1 +1 |
+-------+
| 2 |
+-------+
借助这一特性,我们就有机会编写具备较好移植性的SQL语句, 在使用MySQL独有特性的同时,保证了SQL语句在其它数据库也能够成功被执行:
create table t1(col1 int) /*! engine=MyISAM */;
select /*! STRAIGHT_JOIN */ col1 from t1;
...
/*!version-number SQL*/
在日常使用中,我们还会经常看到如下格式的注释语句:
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE */
/*!80000 SET SESSION information_schema_stats_expiry=0 */
/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
/*!
后跟的5位数字为版本指示器,其与数据库版本的对应规则为:
'/' '*' '!', followed by exactly
第1位:主版本号(VERSION_MAJOR),
第2, 3位:小版本号(VERSION_MINOR),
第4, 5位:Patch号(VERSION_PATCH)
示例:
32302 -> 3.23.02
50738 -> 5.7.38
80025 -> 8.0.25
以上述第一个注释语句为例,它的含义可以描述为:当MySQL数据库版本为5.0.3或更高版本时,将SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE
读取出来参与SQL语法解析,并最终被执行;当MySQL版本低于5.0.3时,该行语句被当成一个普通的注释。不难看出,带version_number的可执行注释,是为了解决不同的MySQL版本之间的兼容问题。以8.0.23版本新增的Invisible Columnsw
为例, 如下建表语句在8.0.23版本之前将无法执行:
CREATE TABLE t1 (i INT, j DATE INVISIBLE);
如下的语句改造则保证了建表语句的向下版本兼容:
CREATE TABLE t1 (i INT, j DATE /*!80023 INVISIBLE */);
实际上,在我们常用的工具mysqldump也借用这个特性,使得产生的SQL能够兼容不同的数据库版本:
/*mysqldump 代码片段*/
dump_fputs(
sql_file,
"/*!50717 SELECT COUNT(*) INTO @rocksdb_has_p_s_session_variables"
" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA ="
" 'performance_schema' AND TABLE_NAME = 'session_variables'"
" */;\n"
"/*!50717 SET @rocksdb_get_is_supported = IF"
" (@rocksdb_has_p_s_session_variables, 'SELECT COUNT(*) INTO"
" @rocksdb_is_supported FROM performance_schema.session_variables"
" WHERE VARIABLE_NAME=\\'rocksdb_bulk_load\\'', 'SELECT 0') */;\n"
"/*!50717 PREPARE s FROM @rocksdb_get_is_supported */;\n"
"/*!50717 EXECUTE s */;\n"
"/*!50717 DEALLOCATE PREPARE s */;\n"
"/*!50717 SET @rocksdb_enable_bulk_load = IF"
" (@rocksdb_is_supported, 'SET SESSION rocksdb_bulk_load = 1',"
" 'SET @rocksdb_dummy_bulk_load = 0') */;\n"
"/*!50717 PREPARE s FROM @rocksdb_enable_bulk_load */;\n"
"/*!50717 EXECUTE s */;\n"
"/*!50717 DEALLOCATE PREPARE s */;\n");
check_io(sql_file);
在show create table等语句中我们也能看到类似的应用(sql/sql_show.cc):
mysql> create table t1 (i int, j date invisible);
Query OK, 0 rows affected (0.03 sec)
mysql> show create table t1;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`i` int DEFAULT NULL,
`j` date DEFAULT NULL /*!80023 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
结语
MySQL Server提供的可执行注释功能,在横向跨数据库和纵向跨版本兼容上都为数据库用户提供了较大支持,是一个比较便利的特性。功能实现上,MySQL Server是在词法解析阶段先对语句做了一遍拦截,针对/*!
按具体情况做了特殊处理,如有兴趣您可以参考MySQL的词法解析相关源码。注:以8.0.25版本为例,它的相关解析放在sql_lex.cc的lex_one_token()中,在其中您也能看见MySQL词法解析器是怎么对optimizer hints comments(格式: /*+ optimizer_hints */
)进行处理的。
Enjoy GreatSQL :)
《深入浅出MGR》视频课程
戳此小程序即可直达B站
https://www.bilibili.com/medialist/play/1363850082?business=space_collection&business_id=343928&desc=0
文章推荐:
关于 GreatSQL
GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
Gitee: https://gitee.com/GreatSQL/GreatSQL
GitHub: https://github.com/GreatSQL/GreatSQL
Bilibili:
https://space.bilibili.com/1363850082/video
相关文章
- Mysql:2003 - Can't connect to MySQL server on 'localhost' (10061 "Unknown error") 解决方法
- MySQL触发器:优化数据库执行时间(mysql触发器时间)
- 解决电脑上MySQL重装添新(电脑重装mysql)
- 填坑记:MySQL常见问题及如何解决(mysql常见的坑)
- 使用 MySQL 同步复制构建高可用性(mysql同步复制)
- MySQL中获取当前日期的方法(mysql获得当前日期)
- MySQL查询执行时间简单掌握(mysql查看执行时间)
- MySQL执行引擎简介:常用的五种执行引擎及其优缺点(mysql执行引擎)
- 如何实现MySQL两张表的同步?(mysql两张表同步)
- 使用Cacti监控MySQL性能(cacti监控mysql)
- 提高开发效率,掌握MySQL数据库执行语句的技巧与方法(mysql数据库执行语句)
- 优化MySQL语句,提高性能(mysql语句性能)
- 提升效率:用MySQL查看SQL代码的性能(mysql查看sql执行效率)
- MySQL中C语言实现事务执行(c 事务执行mysql)
- MySQL中IN操作的高效优化(mysql 中in的优化)
- MySQL批量执行多条语句的方法(c mysql多条语句吗)
- MySQL下载探索后续选项(mysql下载后面的选项)