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社区助手
微信好友,发送验证信息加群
。