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 :)
文章举荐:
乏味的 SQL DIGEST
ulimits 不失效导致数据库启动失败和相干设置阐明
MGR 及 GreatSQL 资源汇总
GreatSQL MGR FAQ
在 Linux 下源码编译装置 GreatSQL/MySQL
## 对于 GreatSQL
GreatSQL 是由万里数据库保护的 MySQL 分支,专一于晋升 MGR 可靠性及性能,反对 InnoDB 并行查问个性,是实用于金融级利用的 MySQL 分支版本。
Gitee:
https://gitee.com/GreatSQL/GreatSQL
GitHub:
https://github.com/GreatSQL/GreatSQL
Bilibili:
https://space.bilibili.com/1363850082/favlist
技术交换群:
微信:扫码增加
GreatSQL 社区助手
微信好友,发送验证信息加群
。