不可不知的 MySQL 升级利器及 5.7 升级到 8.0 的注意事项

数据库升级是一项苦乐参半的工程。好消息是,通过升级,你可以享受到新版本带来的新功能和性能提升。令人担忧的是,新版本可能与旧版本不兼容,这主要体现在以下三个方面:

[En]

Database upgrade is a bittersweet project. The good news is that through the upgrade, you can enjoy the new features and performance improvements brought by the new version. The worry is that the new version may not be compatible with the old version, which is mainly reflected in the following three aspects:

因此,在升级在线数据库之前,通常会在测试环境中进行大量测试,包括功能测试和性能测试。

[En]

Therefore, before upgrading the online database, a large number of tests are generally carried out in the test environment, including functional testing and performance testing.

很多人可能会觉得麻烦,所以对升级抱着一种不主动、也拒绝的态度,新版本怎么会有更好的性能、更多的新功能,而老版本在产品维护周期结束后也存在安全隐患。

[En]

Many people may find it troublesome, so they take a “do not take the initiative, also refuse” attitude towards the upgrade, how can the new version have better performance and more new features, and the old version also has security risks after the end of the product maintenance cycle.

升还是不升呢?that is a question。

下面我们介绍一个 MySQL 升级利器,可极大减轻 DBA 包括开发童鞋在升级数据库时的心智负担和工作负担。

这个利器就是 pt-upgrade。

pt-upgrade 是 Percona Toolkit 中的一个工具,可帮忙我们从业务 SQL 层面检查新老版本的兼容性。

它的检测思路很简单,给定一个 SQL,分别在两个不同版本的实例上执行,看看是否一致。

具体地说,它检查以下内容:

[En]

Specifically, it examines the following:

  • Row count:查询返回的行数是否一致。
  • Row data:查询的结果是否一致。
  • Warnings:是否提示 warning。正常来说,要么都提示 warning,要么都不提示 warning。
  • Query time:查询时间是否在同一个量级,或者新版本的执行时间是否更短。
  • Query errors:查询如果在一个实例中出现语法错误,会提示 Query errors。
  • SQL errors:查询如果在两个实例中同时出现语法错误,会提示 SQL errors。

pt-upgrade 的使用比较简单,只需提供两个实例的 DSN (实例连接信息)和文件名。

常见用法有以下两种:

(1)直接比较一个文件中的 SQL 在两个实例中的执行效果。

# pt-upgrade h=host1 h=host2 slow.log

可通过 –type 指定文件的类型,支持 slowlog(慢日志),genlog(General Log),binlog(通过 mysqlbinlog 解析后的文本文件),rawlog( SQL语句 ),tcpdump。不指定,则默认是慢日志。

(2)先生成一个基准测试结果,然后再基于这个结果测试其它环境的兼容性。

#&#xA0;pt-upgrade&#xA0;h=host1&#xA0;--save-results&#xA0;host1_results/&#xA0;slow.log<br>#&#xA0;pt-upgrade&#xA0;host1_results1/&#xA0;h=host2

第二种情况适用于无法同时访问两个实例,或者需要根据基准测试结果进行多个测试的情况。

[En]

The second usage applies when two instances cannot be accessed at the same time, or multiple tests are required based on a benchmark result.

看下面这个 Demo。

pt_upgrade_test.sql 包含了若干条测试语句。

#&#xA0;cat&#xA0;/tmp/pt_upgrade_test.sql<br>select&#xA0;"a&#xA0;word&#xA0;a"&#xA0;REGEXP&#xA0;"[[:<:]]word[[:>:]]";<br>select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;desc;<br>grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;'u1'@'%'&#xA0;identified&#xA0;by&#xA0;'123456';<br>create&#xA0;table&#xA0;employees.t1(id&#xA0;int&#xA0;primary&#xA0;key,c1&#xA0;text&#xA0;not&#xA0;null&#xA0;default&#xA0;(''));&#xA0;<br>select&#xA0;*&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no;<br></:]]word[[:>

这里给出的几条测试语句都极具代表性,都是升级过程中需要注意的 SQL。

下面我们看看这些语句在 MySQL 5.7 和 MySQL 8.0 中的执行情况。

#&#xA0;pt-upgrade&#xA0;h=127.0.0.1,P=3307,u=pt_user,p=pt_pass&#xA0;h=127.0.0.1,P=3306,u=pt_user,p=pt_pass&#xA0;--type&#xA0;rawlog&#xA0;/tmp/pt_upgrade_test.sql&#xA0;--no-read-only<br><br>#-----------------------------------------------------------------------<br>#&#xA0;Logs<br>#-----------------------------------------------------------------------<br><br>File:&#xA0;/tmp/pt_upgrade_test.sql<br>Size:&#xA0;311<br><br>#-----------------------------------------------------------------------<br>#&#xA0;Hosts<br>#-----------------------------------------------------------------------<br><br>host1:<br><br>&#xA0;&#xA0;DSN:&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;h=127.0.0.1,P=3307<br>&#xA0;&#xA0;hostname:&#xA0;&#xA0;slowtech<br>&#xA0;&#xA0;MySQL:&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;MySQL&#xA0;Community&#xA0;Server&#xA0;(GPL)&#xA0;5.7.36<br><br>host2:<br><br>&#xA0;&#xA0;DSN:&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;h=127.0.0.1,P=3306<br>&#xA0;&#xA0;hostname:&#xA0;&#xA0;slowtech<br>&#xA0;&#xA0;MySQL:&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;MySQL&#xA0;Community&#xA0;Server&#xA0;-&#xA0;GPL&#xA0;8.0.27<br><br>########################################################################<br>#&#xA0;Query&#xA0;class&#xA0;00A13DD81BF65D41<br>########################################################################<br><br>Reporting&#xA0;class&#xA0;because&#xA0;it&#xA0;has&#xA0;diffs,&#xA0;but&#xA0;hasn't&#xA0;been&#xA0;reported&#xA0;yet.<br><br>Total&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Unique&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Discarded&#xA0;queries&#xA0;&#xA0;0<br><br>grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;?@?&#xA0;identified&#xA0;by&#xA0;?;<br><br>##<br>##&#xA0;Query&#xA0;errors&#xA0;diffs:&#xA0;1<br>##<br><br>--&#xA0;1.<br><br>No&#xA0;error<br><br>vs.<br><br>DBD::mysql::st&#xA0;execute&#xA0;failed:&#xA0;You&#xA0;have&#xA0;an&#xA0;error&#xA0;in&#xA0;your&#xA0;SQL&#xA0;syntax;&#xA0;check&#xA0;the&#xA0;manual&#xA0;that&#xA0;corresponds&#xA0;to&#xA0;your&#xA0;MySQL&#xA0;server&#xA0;version&#xA0;for&#xA0;the&#xA0;right&#xA0;syntax&#xA0;to&#xA0;use&#xA0;near&#xA0;'identified&#xA0;by&#xA0;'123456''&#xA0;at&#xA0;line&#xA0;1&#xA0;[for&#xA0;Statement&#xA0;"grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;'u1'@'%'&#xA0;identified&#xA0;by&#xA0;'123456';"]<br><br>grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;'u1'@'%'&#xA0;identified&#xA0;by&#xA0;'123456';<br><br>########################################################################<br>#&#xA0;Query&#xA0;class&#xA0;296E46FE3AEE9B6C<br>########################################################################<br><br>Reporting&#xA0;class&#xA0;because&#xA0;it&#xA0;has&#xA0;SQL&#xA0;errors,&#xA0;but&#xA0;hasn't&#xA0;been&#xA0;reported&#xA0;yet.<br><br>Total&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Unique&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Discarded&#xA0;queries&#xA0;&#xA0;0<br><br>select&#xA0;*&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no;<br><br>##<br>##&#xA0;SQL&#xA0;errors:&#xA0;1<br>##<br><br>--&#xA0;1.<br><br>On&#xA0;both&#xA0;hosts:<br><br>DBD::mysql::st&#xA0;execute&#xA0;failed:&#xA0;Expression&#xA0;#1&#xA0;of&#xA0;SELECT&#xA0;list&#xA0;is&#xA0;not&#xA0;in&#xA0;GROUP&#xA0;BY&#xA0;clause&#xA0;and&#xA0;contains&#xA0;nonaggregated&#xA0;column&#xA0;'employees.dept_emp.emp_no'&#xA0;which&#xA0;is&#xA0;not&#xA0;functionally&#xA0;dependent&#xA0;on&#xA0;columns&#xA0;in&#xA0;GROUP&#xA0;BY&#xA0;clause;&#xA0;this&#xA0;is&#xA0;incompatible&#xA0;with&#xA0;sql_mode=only_full_group_by&#xA0;[for&#xA0;Statement&#xA0;"select&#xA0;*&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no;"]<br><br>select&#xA0;*&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no;<br><br>########################################################################<br>#&#xA0;Query&#xA0;class&#xA0;8B81ACF1E68DE066<br>########################################################################<br><br>Reporting&#xA0;class&#xA0;because&#xA0;it&#xA0;has&#xA0;diffs,&#xA0;but&#xA0;hasn't&#xA0;been&#xA0;reported&#xA0;yet.<br><br>Total&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Unique&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Discarded&#xA0;queries&#xA0;&#xA0;0<br><br>create&#xA0;table&#xA0;employees.t?(id&#xA0;int&#xA0;primary&#xA0;key,c?&#xA0;text&#xA0;not&#xA0;?&#xA0;default&#xA0;(?));<br><br>##<br>##&#xA0;Query&#xA0;errors&#xA0;diffs:&#xA0;1<br>##<br><br>--&#xA0;1.<br><br>DBD::mysql::st&#xA0;execute&#xA0;failed:&#xA0;You&#xA0;have&#xA0;an&#xA0;error&#xA0;in&#xA0;your&#xA0;SQL&#xA0;syntax;&#xA0;check&#xA0;the&#xA0;manual&#xA0;that&#xA0;corresponds&#xA0;to&#xA0;your&#xA0;MySQL&#xA0;server&#xA0;version&#xA0;for&#xA0;the&#xA0;right&#xA0;syntax&#xA0;to&#xA0;use&#xA0;near&#xA0;'(''))'&#xA0;at&#xA0;line&#xA0;1&#xA0;[for&#xA0;Statement&#xA0;"create&#xA0;table&#xA0;employees.t1(id&#xA0;int&#xA0;primary&#xA0;key,c1&#xA0;text&#xA0;not&#xA0;null&#xA0;default&#xA0;(''));&#xA0;"]<br><br>vs.<br><br>No&#xA0;error<br><br>create&#xA0;table&#xA0;employees.t1(id&#xA0;int&#xA0;primary&#xA0;key,c1&#xA0;text&#xA0;not&#xA0;null&#xA0;default&#xA0;(''));<br><br>########################################################################<br>#&#xA0;Query&#xA0;class&#xA0;92E8E91AB47593A5<br>########################################################################<br><br>Reporting&#xA0;class&#xA0;because&#xA0;it&#xA0;has&#xA0;diffs,&#xA0;but&#xA0;hasn't&#xA0;been&#xA0;reported&#xA0;yet.<br><br>Total&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Unique&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Discarded&#xA0;queries&#xA0;&#xA0;0<br><br>select&#xA0;?&#xA0;regexp&#xA0;?;<br><br>##<br>##&#xA0;Query&#xA0;errors&#xA0;diffs:&#xA0;1<br>##<br><br>--&#xA0;1.<br><br>No&#xA0;error<br><br>vs.<br><br>DBD::mysql::st&#xA0;execute&#xA0;failed:&#xA0;Illegal&#xA0;argument&#xA0;to&#xA0;a&#xA0;regular&#xA0;expression.&#xA0;[for&#xA0;Statement&#xA0;"select&#xA0;"a&#xA0;word&#xA0;a"&#xA0;REGEXP&#xA0;"[[:<:]]word[[:>:]]";"]<br><br>select&#xA0;"a&#xA0;word&#xA0;a"&#xA0;REGEXP&#xA0;"[[:<:]]word[[:>:]]";<br><br>########################################################################<br>#&#xA0;Query&#xA0;class&#xA0;D3F390B1B46CF9EA<br>########################################################################<br><br>Reporting&#xA0;class&#xA0;because&#xA0;it&#xA0;has&#xA0;diffs,&#xA0;but&#xA0;hasn't&#xA0;been&#xA0;reported&#xA0;yet.<br><br>Total&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Unique&#xA0;queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>Discarded&#xA0;queries&#xA0;&#xA0;0<br><br>select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;desc;<br><br>##<br>##&#xA0;Query&#xA0;errors&#xA0;diffs:&#xA0;1<br>##<br><br>--&#xA0;1.<br><br>No&#xA0;error<br><br>vs.<br><br>DBD::mysql::st&#xA0;execute&#xA0;failed:&#xA0;You&#xA0;have&#xA0;an&#xA0;error&#xA0;in&#xA0;your&#xA0;SQL&#xA0;syntax;&#xA0;check&#xA0;the&#xA0;manual&#xA0;that&#xA0;corresponds&#xA0;to&#xA0;your&#xA0;MySQL&#xA0;server&#xA0;version&#xA0;for&#xA0;the&#xA0;right&#xA0;syntax&#xA0;to&#xA0;use&#xA0;near&#xA0;'desc'&#xA0;at&#xA0;line&#xA0;1&#xA0;[for&#xA0;Statement&#xA0;"select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;desc;"]<br><br>select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;desc;<br><br>#-----------------------------------------------------------------------<br>#&#xA0;Stats<br>#-----------------------------------------------------------------------<br><br>failed_queries&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1<br>not_select&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0<br>queries_filtered&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0<br>queries_no_diffs&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0<br>queries_read&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;5<br>queries_with_diffs&#xA0;&#xA0;&#xA0;&#xA0;0<br>queries_with_errors&#xA0;&#xA0;&#xA0;4<br></:]]word[[:></:]]word[[:>

3307,3306 端口分别对应 MySQL 5.7、MySQL 8.0 实例。

对于文件中的每一个 SQL ,都会在这两个实例中执行。如果每个差异 SQL 的结果都打印出来的话,最后的输出将十分庞杂。为了简化最后的输出结果,pt-upgrade 会对 SQL 进行分类,同一类 SQL 的输出次数受到 –max-class-size 和 –max-examples 的限制。

结合执行的 SQL,我们分析下输出结果。

SQL 3

grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;'u1'@'%'&#xA0;identified&#xA0;by&#xA0;'123456';

在 MySQL 8.0 之前,对一个用户进行授权(grant)操作,如果该用户不存在,会隐式创建。而在 MySQL 8.0 中,该命令会直接报错,必须先创建用户,再授权。

所以,上面这条 SQL 需拆分为以下两条 SQL 来执行。

create&#xA0;user&#xA0;'u1'@'%'&#xA0;identified&#xA0;by&#xA0;'123456';<br>grant&#xA0;select&#xA0;on&#xA0;employees.*&#xA0;to&#xA0;'u1'@'%';

这个查询只在一个实例中出现语法错误,所以 pt-upgrade 会将其归类为 Query errors 。

SQL 5

select&#xA0;*&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no;

从 MySQL 5.7 开始,SQL_MODE 的默认值发生了变化,包含了 ONLY_FULL_GROUP_BY 。

ONLY_FULL_GROUP_BY 要求,对于 GROUP BY 操作,SELECT 列表中只能出现分组列(即 GROUP BY 后面的列)和聚合函数( SUM,AVG,MAX等 ),不允许出现其它非分组列。

很明显,上面这条 SQL 违背了这一要求。所以,无论是在 MySQL 5.7 还是 8.0 中,该 SQL 都会报错。

这个查询在两个实例中都出现了语法错误,所以 pt-upgrade 会将其归类为 SQL errors 。

SQL 4

create&#xA0;table&#xA0;employees.t1(id&#xA0;int&#xA0;primary&#xA0;key,c1&#xA0;text&#xA0;not&#xA0;null&#xA0;default&#xA0;(''));

从 MySQL 8.0.13 开始,允许对 BLOB,TEXT,GEOMETRY 和 JSON 字段设置默认值。之前版本,则不允许。

SQL 1

select&#xA0;"a&#xA0;word&#xA0;a"&#xA0;REGEXP&#xA0;"[[:<:]]word[[:>:]]";<br></:]]word[[:>

在 MySQL 8.0 中,正则表达式底层库由 Henry Spencer 调整为了 International Components for Unicode (ICU)。

在 Henry Spencer 库中,[[:

select&#xA0;"a&#xA0;word&#xA0;a"&#xA0;REGEXP&#xA0;"\\bword\\b";

SQL 2

select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;desc;

在 MySQL 8.0 之前,如果我们要对分组后的结果进行排序,可使用 GROUP BY col_name ASC/DESC ,没有指定排序列,默认是对分组列进行排序。

在 MySQL 8.0 中,不再支持这一语法,如果要进行排序,需显式指定排序列。所以,对于上面这个 SQL,在 MySQL 8.0 中的写法如下。

select&#xA0;dept_no,count(*)&#xA0;from&#xA0;employees.dept_emp&#xA0;group&#xA0;by&#xA0;dept_no&#xA0;order&#xA0;by&#xA0;dept_no&#xA0;desc;

–[no]read-only

默认情况下,pt-upgrade 只会执行 SELECT 和 SET 操作。如果要执行其它操作,必须指定 –no-read-only。

–[no]create-upgrade-table,–upgrade-table

默认情况下,pt-upgrade 会在目标实例上创建一张 percona_schema.pt_upgrade 表(由 –upgrade-table 参数指定),每执行完一个 SQL,都会执行一次 SELECT * FROM percona_schema.pt_upgrade LIMIT 1 以清除上一个 SQL 有可能出现的 warning 。

–max-class-size,–max-examples

pt-upgrade 会对 SQL 进行分类,这两个参数可用来限制同一类 SQL 输出的数量。其中,–max-class-size 用来限制不重复 SQL 的数量,默认是 1000。–max-examples 用来限制 SQL 的数量,包括重复 SQL,默认是 3。

pt-upgrade 基于什么对 SQL 进行分类呢?fingerprint。

fingerprint 这个术语,我们在很多工具中都会看到,如 ProxySQL,pt-query-digest,可理解为基于某些规则,提取 SQL 的一般形式,类似于 JDBC 中的 PreparedStatement 。

譬如下面这几条 SQL,就可归为同一类 select c? from d?t? where id=?

select&#xA0;c1&#xA0;from&#xA0;db1.t1&#xA0;where&#xA0;id=1;<br>select&#xA0;c1&#xA0;from&#xA0;db1.t1&#xA0;where&#xA0;id=1;<br>select&#xA0;c1&#xA0;from&#xA0;db1.t1&#xA0;where&#xA0;id=2;<br>select&#xA0;c2&#xA0;from&#xA0;db1.t1&#xA0;where&#xA0;id=3;<br>select&#xA0;c3&#xA0;from&#xA0;db1.t2&#xA0;where&#xA0;id=4;<br>select&#xA0;c4&#xA0;from&#xA0;db2.t3&#xA0;where&#xA0;id=5;<br>select&#xA0;c5&#xA0;from&#xA0;db2.t4&#xA0;where&#xA0;id=6;

Percona Toolkit 中的提取规则如下:

–save-results

将查询结果保存到目录。

[En]

Save the query results to the directory.

#&#xA0;pt-upgrade&#xA0;h=127.0.0.1,P=3307,u=pt_user,p=pt_pass&#xA0;--save-results&#xA0;/tmp/pt_upgrade_result&#xA0;--type&#xA0;rawlog&#xA0;/tmp/pt_upgrade_test.sql&#xA0;--no-read-only&#xA0;<br>#&#xA0;pt-upgrade&#xA0;/tmp/pt_upgrade_result/&#xA0;h=127.0.0.1,P=3306,u=pt_user,p=pt_pass

在执行 pt-upgrade 之前,必须确保两个实例中的数据完全一致,且不会发生变更,否则会产生误判。

基于此,pt-upgrade 更适合在测试环境或开发环境使用,不建议在生产环境上使用。

MySQL 5.7 升级到 MySQL 8.0,目前已知的,需要注意的点主要有以下两个:

一、不再支持 GROUP BY col_name ASC/DESC。如果要排序,需显式指定排序列。

二、MySQL 8.0 的正则表达式底层库由 Henry Spencer 调整为了 International Components for Unicode (ICU),Spencer 库的部分语法不再支持。具体来说:

  1. Spencer 库是以字节方式工作的,不是多字节安全的,在碰到多字节字符时有可能不会得到预期效果。而 ICU 支持完整的 Unicode 并且是多字节安全的。
mysql&#xA0;5.7>&#xA0;select&#xA0;'&#x10D;'&#xA0;regexp&#xA0;'^.$';<br>+-------------------+<br>|&#xA0;'&#x10D;'&#xA0;regexp&#xA0;'^.$'&#xA0;&#xA0;|<br>+-------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0&#xA0;|<br>+-------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;'&#x10D;'&#xA0;regexp&#xA0;'^.$';<br>+-------------------+<br>|&#xA0;'&#x10D;'&#xA0;regexp&#xA0;'^.$'&#xA0;&#xA0;|<br>+-------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+-------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)
  1. 在 Spencer 库中, .可用来匹配任何字符,包括回车符(\r)和换行符(\n)。而在 ICU 中, . 默认不会匹配回车符和换行符。如果要匹配,需指定正则修饰符 n
mysql&#xA0;5.7>&#xA0;select&#xA0;'new\nline'&#xA0;regexp&#xA0;'new.line';<br>+-------------------------------+<br>|&#xA0;'new\nline'&#xA0;regexp&#xA0;'new.line'&#xA0;|<br>+-------------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+-------------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;'new\nline'&#xA0;regexp&#xA0;'new.line';<br>+-------------------------------+<br>|&#xA0;'new\nline'&#xA0;regexp&#xA0;'new.line'&#xA0;|<br>+-------------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0&#xA0;|<br>+-------------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;regexp_like('new\nline','new.line','n');<br>+-----------------------------------------+<br>|&#xA0;regexp_like('new\nline','new.line','n')&#xA0;|<br>+-----------------------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+-----------------------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)
  1. Spencer 库支持通过 [[:
mysql&#xA0;5.7>&#xA0;select&#xA0;'a&#xA0;word&#xA0;a'&#xA0;regexp&#xA0;'[[:<:]]word[[:>:]]';<br>+----------------------------------------+<br>|&#xA0;'a&#xA0;word&#xA0;a'&#xA0;regexp&#xA0;'[[:<:]]word[[:>:]]'&#xA0;|<br>+----------------------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+----------------------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;'a&#xA0;word&#xA0;a'&#xA0;regexp&#xA0;'[[:<:]]word[[:>:]]';<br>ERROR&#xA0;3685&#xA0;(HY000):&#xA0;Illegal&#xA0;argument&#xA0;to&#xA0;a&#xA0;regular&#xA0;expression.<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;'a&#xA0;word&#xA0;a'&#xA0;regexp&#xA0;'\\bword\\b';<br>+--------------------------------+<br>|&#xA0;'a&#xA0;word&#xA0;a'&#xA0;regexp&#xA0;'\\bword\\b'&#xA0;|<br>+--------------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+--------------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br></:]]word[[:></:]]word[[:></:]]word[[:>
  1. Spencer 库支持 [.characters.],这里的 characters 既可以是字符,又可以是字符名称,譬如字符 : 对应的字符名称是 colon 。 ICU 中不支持字符名称。
mysql&#xA0;5.7>&#xA0;select&#xA0;':'&#xA0;regexp&#xA0;'[[.:.]]';<br>+----------------------+<br>|&#xA0;':'&#xA0;regexp&#xA0;'[[.:.]]'&#xA0;|<br>+----------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+----------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;5.7>&#xA0;select&#xA0;':'&#xA0;regexp&#xA0;'[[.colon.]]';<br>+--------------------------+<br>|&#xA0;':'&#xA0;regexp&#xA0;'[[.colon.]]'&#xA0;|<br>+--------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+--------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.01&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;':'&#xA0;regexp&#xA0;'[[.:.]]';<br>+----------------------+<br>|&#xA0;':'&#xA0;regexp&#xA0;'[[.:.]]'&#xA0;|<br>+----------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+----------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;':'&#xA0;regexp&#xA0;'[[.colon.]]';<br>+--------------------------+<br>|&#xA0;':'&#xA0;regexp&#xA0;'[[.colon.]]'&#xA0;|<br>+--------------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;0&#xA0;|<br>+--------------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)
  1. ICU 中如果要匹配右括号 ) ,需使用转义符。
mysql&#xA0;5.7>&#xA0;select&#xA0;')'&#xA0;regexp&#xA0;(')');<br>+------------------+<br>|&#xA0;')'&#xA0;regexp&#xA0;(')')&#xA0;|<br>+------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;')'&#xA0;regexp&#xA0;(')');<br>ERROR&#xA0;3691&#xA0;(HY000):&#xA0;Mismatched&#xA0;parenthesis&#xA0;in&#xA0;regular&#xA0;expression.<br><br>mysql&#xA0;8.0>&#xA0;select&#xA0;')'&#xA0;regexp&#xA0;('\\)');<br>+--------------------+<br>|&#xA0;')'&#xA0;regexp&#xA0;('\\)')&#xA0;|<br>+--------------------+<br>|&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;1&#xA0;|<br>+--------------------+<br>1&#xA0;row&#xA0;in&#xA0;set&#xA0;(0.00&#xA0;sec)

相信有了 pt-upgrade 的加持,后续我们再进行数据库升级时心里会有底很多。

MySQL 8.0 虽然引入了很多新特性,但升级时需要注意的点其实也不多。

除了上面提到的两点外,如果发现其他需要注意的地方,也会及时更新到留言中。欢迎您继续关注我们。

[En]

In addition to the two points mentioned above, if you find other points that need to be paid attention to later, they will also be updated to the message in time. You are welcome to follow us continuously.

除了 pt-upgrade,另外一个推荐的数据库升级工具是 MySQL Shell 中的 util.checkForServerUpgrade()。

与 pt-upgrade 不一样的是,util.checkForServerUpgrade() 更多的是从实例的基础数据本身来判定实例是否满足升级条件,譬如是否使用了移除的函数、表名是否存在冲突等,一共有 21 个检查项,这个工具我们后面也会介绍,敬请期待。

Original: https://www.cnblogs.com/ivictor/p/16275919.html
Author: iVictor
Title: 不可不知的 MySQL 升级利器及 5.7 升级到 8.0 的注意事项

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/505377/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 分布式锁的实现

    什么是分布式锁? 为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLo…

    数据库 2023年6月6日
    099
  • JUC学习

    如何正确停止线程? 停止线程应该是一种通知协作的方式,比如interrupt,但是它仅仅是通知线程,线程拥有完全的自主权,根据自身业务来判断什么时候停止,因为如果选择立即停止就可能…

    数据库 2023年6月16日
    089
  • CentOs安装Nginx

    安装 gcc pcre pcre-devel zlib OpenSSL 安装 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需…

    数据库 2023年6月11日
    072
  • 代码随想录-数组篇

    上次刷没刷完整,和李哥做字节的题感觉先前刷的题白刷了,故打算从头到尾完整走一遍。 二分法 1-1.二分查找 力扣题目链接 给定一个 n 个元素有序的(升序)整型数组 nums 和一…

    数据库 2023年6月14日
    099
  • 第十三章 后置处理Bean

    BeanPostProcessor: 对Spring工厂所创建的对象,进行再加工 注意: BeanPostProcessor是一个接口 程序员实现BeanPostProcessor…

    数据库 2023年6月14日
    070
  • 01-MySQL基础

    1、数据库的基本概念 1.1、文件操作数据的缺点 查找,增加,修改,删除数据等操作比较麻烦(特别是txt),效率低 1.2、数据库的介绍 存储和管理数据的仓库 英文单词为Dtaba…

    数据库 2023年5月24日
    055
  • Installing Superset最新版本安装(笔记)

    官方文档:https://superset.apache.org/docs/installation/installing-superset-from-scratch 由于在cen…

    数据库 2023年6月14日
    094
  • MySQL锁(乐观锁、悲观锁、多粒度锁)

    锁 并发事务可能会发生什么情况: [En] What may happen to concurrent transactions: 读-读事务并发:此时是没有问题的,读操作不会对记…

    数据库 2023年5月24日
    084
  • [spring]spring静态代理和aop

    10.代理模式 代理模式的分类: 静态代理 动态代理 关系分析 抽象角色:一般会使用接口或者抽象类 真实角色:被代理的角色 代理角色:代理真实的角色,做一些附属的操作 客户:访问代…

    数据库 2023年6月16日
    084
  • Mysql 的Innodb引擎和Myisam数据结构和区别

    先大体看一下MySQL的SQL layer层的一个架构流程: 简要介绍一些关键模块: [En] Give a brief description of some key modul…

    数据库 2023年5月24日
    080
  • 基于 ZooKeeper 的分布式锁实现

    ZK 基本概念 apache hadoop 下面的子项目,是一个树形目录服务 字面意思就是动物管理员,诞生之初用来管理 hadoop(大象)、Hive(蜜蜂)、Pig(小猪) 用于…

    数据库 2023年6月6日
    077
  • 多商户商城系统功能拆解21讲-平台端分销订单

    多商户商城系统,也称为B2B2C(BBC)平台电商模式多商家商城系统。可以快速帮助企业搭建类似拼多多/京东/天猫/淘宝的综合商城。 多商户商城系统支持商家入驻加盟,同时满足平台自营…

    数据库 2023年6月14日
    091
  • 500 ZuulException: Forwarding error

    com.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud.ne…

    数据库 2023年6月16日
    078
  • Docker三种文件系统总结

    概述 容器持久化,相比小伙伴都不陌生。通过Docker的volume,我们可以非常方便的实现容器数据的持久化存储。但volume之下的文件系统,相比许多小伙伴并不是非常清楚。因而本…

    数据库 2023年6月11日
    0119
  • 2022-8-27 vue 第一天

    什么是vue? Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建…

    数据库 2023年6月14日
    066
  • Django点击图片缩放

    参考信息 用 zoom.js 给博客园中博文的图片添加单击时弹出放大效果:https://www.cnblogs.com/mingc/p/7446492.html 使用 1. 下载…

    数据库 2023年6月9日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球