作者 | Norvald Ryeng
来源 |https://dev.mysql.com/blog-archive/are-you-ready-for-mysql-10/
大家好,我是 JiekeXu,很高兴又和大家见面了,今天和大家一起来看看 你准备好使用 MySQL 10 了吗?欢迎点击上方蓝字“JiekeXu DBA之路”关注我的公众号,标星或置顶,更多干货第一时间到达。
我们都知道,MySQL 官方刚刚发布了 8.1 版,所以现在考虑 10 版是不是有点早?但是 MySQL 5.7 几乎已经到了它的生命周期的尽头,MySQL 工程师已经在研究 8.2 和 8.3。以这种速度,我们可以期望在几年内达到版本 10。无论如何,版本 10 有什么特别之处?实际上,除了它是第一个使用两位数作为主要版本号的版本之外,什么都没有。
在 MySQL 8.1 中,我们进行了一些更改,为 MySQL 10 发布之日做准备。您是否验证了您的应用程序是否已准备好使用 MySQL 10?
让我们来看看我们在 MySQL Server 中做了什么来为此做准备,以及你可以和应该做些什么来证明你的应用程序的未来。
我们做了什么
MySQL 8.1 做了一个小但重要的更改:特殊注释(所谓的“版本注释”)中的版本号现在可以是六位数,而不是早期版本中的五位数。就这么简单,但它有一些我们将要讨论的后果,但首先让我们回顾一下注释中版本号的整个概念,以及注释为什么以及何时并不总是注释。
不同的 RDBMS 有不同的 SQL 方言。不同版本的 MySQL 也支持 SQL 的不同功能。为了帮助用户编写跨 DBMS 和不同版本的 MySQL 兼容的 SQL,有一些特殊的注释看起来像对其他 DBMS 的注释,但对所有或某些版本的 MySQL 来说却是 SQL。这被广泛使用,例如,在 mysqldump 等工具中,以提供向后兼容的 SQL 语句。让我们看一个简单的例子,一个 points interest 表:
mysql> CREATE TABLE locations (id INTEGER PRIMARY KEY, name VARCHAR(100), position POINT SRID 4326);
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW CREATE TABLE locations\G
*************************** 1. row ***************************
Table: locations
Create Table: CREATE TABLE `locations` (
`id` int NOT NULL,
`name` varchar(100) DEFAULT NULL,
`position` point /*!80003 SRID 4326 */ DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
在这种情况下,位置列上的 SRID 规范是 MySQL 8.0.3 中的一个新功能。旧版本的 MySQL 无法解析此语法,因此语法包含在带有一些特殊语法的注释(不是真正的注释)中:/*!80003 SRID 4326 */
语法将 /*… */ 作为注释。但是,由于注释的第一个字符是感叹号,因此 MySQL 不会将其视为注释。/*!...*/ 对其他 DBMS 来说是注释,但在 MySQL 却不是注释。
此外,感叹号后面的前五个字符是数字,对于 MySQL 来说,这意味着注释不是这些数字指定的版本(或更高版本)中的注释,而是对旧版本的 MySQL 和其他 DBMS 的注释。该格式适用于内容不是 MySQL 版本 x.yy.zz 或更高版本中的注释的注释。x.yy.zz or /* !xyyzz… */
这种格式的问题很明显。x 只有一个数字,版本 10 中有两位数字。如果我们尝试使用六位数字 /* !100000… */ 来表示版本 10.0.0 ,MySQL 会将其解释为指定版本 1.0.0 的五位数字。第六位数字被解释为要在版本 1.0.0 或更高版本中插入的文本的一部分。如果在版本 10.0.0 中引入了 SRID 规范,则注释将读取 ,这将被解释为“0 SRID 4326”,并在 MySQL 1.0.0 及更高版本中导致语法错误。 /*!100000 SRID 4326 */
为了演示效果,我们可以构造一个在所有版本中语法上都有效但具有不同语义的示例:
mysql-8.0.33> SELECT 2 * /*!100000 +2*/ +1;
+-------------+
| 2 * 0 +2 +1 |
+-------------+
| 3 |
+-------------+
1 row in set (0.00 sec)
mysql-8.1.0> SELECT 2 * /*!100000 +2*/ +1;
+---------+
| 2 * +1 |
+---------+
| 2 |
+---------+
1 row in set (0.00 sec)
mysql-10.0.0> SELECT 2 * /*!100000 +2*/ +1;
+------------+
| 2 * +2 +1 |
+------------+
| 5 |
+------------+
1 row in set (0.00 sec)
在这里,我们使用加号可以同时使用一元(表示正数)和二进制(作为加法运算符)的事实,以使它在所有版本中都有效。列标题显示了每个 MySQL 版本如何解释该语句,我们看到 8.0、8.1 和 10.0 对它的处理方式不同(我承认 MySQL 10.0 结果是伪造的,但这是未来版本 10.0 解释它的方式。
8.1 和 10.0 之间的差异是我们期望的。两个版本都明白这是要在版本 10.0.0 及更高版本中插入的文本,但在旧版本中则不然。这意味着 8.1.0 正确理解此注释的内容适用于版本 10.0.0 及更高版本并跳过它,而版本 10.0.0 决定将其包含在查询中。但是 8.0.33 处理得很糟糕。MySQL 8.0 只能理解五位版本号,第六位被解释为要插入的文本的一部分,所以我们用 2 乘以版本号的最后一位,即零。这显然不是本意,应警告用户。这就是为什么从 8.0.34 开始的 MySQL 发出此警告的原因:
mysql-8.0.34> SELECT 2 * /*!100000 +2*/ +1;
+-------------+
| 2 * 0 +2 +1 |
+-------------+
| 3 |
+-------------+
1 row in set, 1 warning (0.00 sec)
Warning (Code 4164): Immediately starting the version comment after the version number is deprecated and may change behavior in a future release. Please insert a white-space character after the version number.
8.0.34 中的结果与 8.0.33 中的结果相同,但有一个警告,表明此语句将来的行为可能会有所不同。正如我们在上面看到的,它肯定会。
MySQL 本身在 SHOW 命令的结果中输出版本注释,mysqldump 在任何地方都使用它们,但我们确保始终打印一个空格字符来分隔要插入的文本中的版本号,因此它们在未来的版本中不会有不同的解释。编写版本注释时也应执行相同的操作。
还有一个向后兼容性问题:MySQL 8.0 并不总是能够在不进行修改的情况下从 MySQL 10 或更高版本加载转储。如果使用版本 10 或更高版本中引入的功能,转储将包含 8.0 会误解的版本注释。转储不太可能在 8.0 中加载而没有错误。每当出现六位数的版本注释时,您可能会遇到语法错误。无论如何,在 MySQL 10 发布时,8.0 预计将是 EOL,因此在 8.0 中从版本 10 导入转储的用例应该非常有限。
你应该做什么
如上所示,构造一个在 8.0 和 10.0 中具有两个有效解释的查询需要一些技巧。您的应用程序中不太可能有这样的东西。但是,可能会出现版本注释,这些注释不会分隔版本号和要用空格字符插入的文本。从 8.0.34 开始,MySQL 每次看到此消息时都会发出警告。您应该修复所有这些情况,以确保与 10.0 及更高版本向前兼容。如果不这样做,查询很可能会失败,并在 10.0 中出现语法错误。MySQL 不在乎你是否使用空格,制表符或新行(CR,LF 和 CRLF 都被接受)。只需将版本号与要插入的文本分开即可。
除了注释之外,还有其他几个接口包含版本号,可以是字符串或者整型:
类型 | 名字 | 数据类型 | 示例值 |
---|---|---|---|
C 函数 | mysql_get_client_info() | String | 8.1.0 |
C 函数 | mysql_get_client_version() | Integer | 80100 |
C 函数 | mysql_get_server_info() | String | 8.1.0 |
C 函数 | mysql_get_server_version() | Integer | 80100 |
C 宏 | MYSQL_SERVER_VERSION | String | 8.1.0 |
C 宏 | MYSQL_BASE_VERSION | String | mysqld-8.1 |
C 宏 | MYSQL_VERSION_ID | Integer | 80100 |
C 宏 | LIBMYSQL_VERSION | String | 8.1.0 |
C 宏 | LIBMYSQL_VERSION_ID | Integer | 80100 |
SQL函数 | group_replication_get_communication_protocol() | String | 8.1.0 |
SQL函数 | group_replication_set_communication_protocol() | String | 8.1.0 |
SQL函数 | version() | String | 8.1.0 |
系统变量 | immediate_server_version | Integer | 80100 |
系统变量 | innodb_version | String | 8.1.0 |
系统变量 | original_server_version | Integer | 80100 |
系统变量 | version | String | 8.1.0 |
在所有这些情况下,您的代码可能已经能够处理版本 10,除非您已显式检查版本号。不过,在源代码中搜索这些符号并验证它是否正确处理版本号并没有什么坏处。
现在就做!MySQL 10 即将推出!
英文原文:https://dev.mysql.com/blog-archive/are-you-ready-for-mysql-10/
全文完,希望可以帮到正在阅读的你,如果觉得此文对你有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~
欢迎关注我公众号【JiekeXu DBA之路】,第一时间一起学习新知识!以下三个地址可以找到我,其他地址都属于盗版侵权爬取我的文章,而且代码格式、图片等均有错乱,不方便阅读,欢迎来我公众号或者墨天轮地址关注我,第一时间收获最新消息。
————————————————————————————
公众号:JiekeXu DBA之路
CSDN :https://blog.csdn.net/JiekeXu
墨天轮:https://www.modb.pro/u/4347
————————————————————————————
分享几个数据库备份脚本
Oracle 表碎片检查及整理方案
OGG|Oracle GoldenGate 基础2022 年公众号历史文章合集整理
Oracle 19c RAC 遇到的几个问题
OGG|Oracle 数据迁移后比对一致性
OGG|Oracle GoldenGate 微服务架构
Oracle 查询表空间使用率超慢问题一则
Oracle 11g升级到19c需要关注的几个问题
国产数据库|TiDB 5.4 单机快速安装初体验
Oracle ADG 备库停启维护流程及增量恢复
Linux 环境搭建 MySQL8.0.28 主从同步环境