麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
493
2023-04-24
聊聊 My*** 可执行注释,你懂了吗?
前言
My***当前支持如下3种注释风格:
以'#'开头的单行注释以'-- '开头的单行注释C语言风格的单行/多行注释
如下SQL脚本给出了3种注释风格的示例:
/* 这是一个多行注释示例*/select 1 from dual;select 2 from dual; # 单行注释用例1select 3 from dual; -- 单行注释用例2
可执行注释
为了支持在不同数据库之间的可移植性,My***针对C风格的注释在解析上做了一些扩展,当注释满足如下风格时,My***将会解析并执行注释中的代码:
/*! 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.0250738 -> 5.7.3880025 -> 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)
结语
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。