01 深入专题:MySQL 8.0 新特性

01 深入专题:MySQL 8.0 新特性

这一篇聚焦 MySQL 8.0 的关键新特性:数据字典改造、DDL 即时/原子操作、窗口函数与 CTE、降序索引、不可见索引、HINT 增强、资源组、redo log 重构、临时表机制变化等,帮助快速掌握 8.0 相对 5.7 的核心差异。内容整理自爱可生开源社区《大智小技》系列(2019/2020 两册)技术文章精选。

MySQL 5.7 升级到 8.0 有哪些版本与升级方式要求?

升级要求 MySQL 5.7.9 及以上 GA 版,不支持跨版本升级。升级内容包含升级数据字典表版本和 MySQL server 版本(system 表及 schema 对象)。步骤上,数据字典升级在实例启动过程中自动完成;MySQL 8.0.16 之前需手动执行 mysql_upgrade 升级 Performance_schema、information_schema、sys schema 及用户 schema,8.0.16 起由 mysqld 自动完成。逻辑升级可使用生产配置文件,但需注意其中的废弃项。

MySQL 8.0 HINT 中 index_merge 支持哪两种组合,适用什么查询形态?

index_merge hint 产生两种访问:对 OR 条件用 union(如 rank1=1 or rank2=2 or rank3=2 → union(idx_rank1,idx_rank2,idx_rank3)),对 AND 条件用 intersect(如三列都等于100 → intersect(…))。优化器本因 cardinality 不准选了全表/单索引,hint 强制多索引合并后行数从 32034 降到 1,cost 大幅下降。

MySQL 8.0 regexp_instr 在多字节字符和“第几次出现”场景如何工作?

REGEXP_INSTR(@a, pattern, pos, occurrence) 返回第 occurrence 次匹配起始位置。对多字节中文串 @a=‘中国 美国 … 北京 …’,REGEXP_INSTR(@a,‘北京’,1,1)=17、第2次=29、第3次=41,可见按字符正确计数。也可用字符类如 ‘[:digit:]{2,}’ 匹配至少两位数字并取第2次出现位置。相比导出 sed,8.0 内置函数更实时。

MySQL 8.0 使用错误日志过滤规则 throttle 有什么作用,如何配置?

throttle 用于限流同类日志,避免告警风暴。配置:先 INSTALL COMPONENT ‘file://component_log_filter_dragnet’; 再 SET GLOBAL dragnet.log_error_filter_rules=‘IF prio==WARNING THEN throttle 1/60.’; 表示每 60 秒只允许记录一条 WARNING,其余合并(JSON 日志标记 and_n_more 表示被合并条数)。对比 drop 规则(直接丢弃),throttle 保留抽样。

MySQL 8.0 动态权限中,SUPER 权限未来走向如何,替代思路是什么?

8.0 将 SUPER 细分为多个动态权限(如图中 session_variables_admin、system_variables_admin 等),SUPER 将被废弃(REVOKE 时告警 1287 “The SUPER privilege identifier is deprecated”)。运维应按最小权限原则,仅授予用户实际需要的动态权限子集,而非笼统给 SUPER,降低越权风险。

MySQL 8.0 动态权限是如何对 SUPER 权限进行细分的?

8.0 将权限分为静态权限和动态权限,动态权限是对 SUPER 的细分,未来 SUPER 将废弃。例如只给用户设置变量的权限,可 GRANT SESSION_VARIABLES_ADMIN, SYSTEM_VARIABLES_ADMIN ON . 再 REVOKE SUPER,此时 show warnings 提示“The SUPER privilege identifier is deprecated”。这样避免了 SUPER 过大带来的越权风险。

MySQL 8.0 升级后分区表需要注意什么?

MySQL 8.0 由存储引擎自身提供分区处理程序,服务器不再提供通用分区支持,仅 InnoDB 和 NDB 提供原生分区。若分区表使用其他存储引擎,须转为 InnoDB/NDB 或删除分区。从 5.7 用 mysqldump 获取的备份,导入 8.0 前需确保建表语句中指定支持分区的存储引擎,否则报错。建议升级时统一调整分区表引擎。

MySQL 8.0 字符集迁移中,ALTER TABLE CONVERT 与修改字段字符集对锁和速度有何影响?

ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 会拷贝全表、速度慢、加锁并阻塞写;ALTER TABLE t MODIFY a CHAR CHARACTER SET utf8mb4 同样拷全表加锁。而 ALTER DATABASE sbtest CHARACTER SET utf8mb4 只改元数据,速度很快。因此大表迁移需评估锁与业务影响,建议低峰或搭配方案二的全量导出导入。

MySQL 8.0 的 HINT 在什么场景下能显著改善执行计划?

当统计信息 cardinality 因频繁 DML 变得不准确时,优化器可能选错计划。文中用 index_merge hint 演示:SQL C(rank1=1 or rank2=2 or rank3=2)原全表扫描 32034 行、cost 3243.65;加 /*+ index_merge(t1) */ 后 union 三列索引,扫描 1103 行、cost 441.09。SQL D 加 hint 后 intersect 索引,cost 从 534.34 降到 5.23,约快 100 倍。

MySQL 8.0 的 JSON_TABLE 函数有什么作用,如何使用?

JSON_TABLE 将 JSON 文档转为关系表,便于用 SQL 查询。基本语法:SELECT * FROM JSON_TABLE(@ytt,’$.name[*]’ COLUMNS(f1 VARCHAR(10) PATH ‘$.a’, f2 VARCHAR(10) PATH ‘$.b’)) AS tt; 复杂结构可用 NESTED PATH 嵌套提取多层(如 $.query_block.table、$.cost_info),并用 FOR ORDINALITY 生成行号。文中将四级嵌套的 EXPLAIN JSON 结果成功展开为多列表。

MySQL 8.0 的 cardinality 为什么会影响执行计划,如何更新?

cardinality 是字段唯一值分布(可选择性基数),优化器据此估算每步操作记录数生成计划,高基数字段适合建索引。表经大量 UPDATE/DELETE/INSERT 后 cardinality 可能不准(未达自动更新临界值或手动采样页少),导致计划非最优。MySQL 提供自动与手动更新表 cardinality 的方法(如 ANALYZE TABLE),必要时用 HINT 纠偏。

MySQL 8.0 的正则替换 regexp_replace 如何替换指定第几次出现的子串?

8.0 新增 REGEXP_REPLACE(str,expr,replace,pos,occurrence),如 UPDATE y1 SET str1=REGEXP_REPLACE(str1,‘action’,‘dble’,1,3) 替换第 3 次出现的 action。REGEXP_INSTR 可返回第几次匹配的位置,如 REGEXP_INSTR(@a,‘北京’,1,2) 返回第 2 次“北京”的位置(29),支持多字节字符。此前需写存储函数或导出用 sed 处理。

MySQL 8.0 窗口函数 row_number() 相比 8.0 之前有哪些实现方式?

8.0 之前需用 session 变量(@rn:=@rn+1 配合 IF 重置分组)或 GROUP_CONCAT+FIND_IN_SET 实现分组排名,写法复杂易错。8.0 原生支持 row_number() OVER(PARTITION BY … ORDER BY …),如按课程分组取成绩前三:row_number() over(partition by b.cname order by c.score desc)。文中学生/课程/成绩示例两种结果一致,但窗口函数更简洁。

MySQL 8.0 窗口函数详解里,8.0 之前用 session 变量实现分组排名的原理是什么?

用两个变量 @rn(序号)和 @cid(当前分组字段)初始化为 0/’’,内层先 ORDER BY cid, score DESC,外层 IF(@cid=c.cid, @rn:=@rn+1, @rn:=1) 实现同组自增、换组重置,并将 @cid:=c.cid 记录分组。再加 WHERE ranking_score<=3 取前三。此法依赖排序顺序,易因执行计划变化出错,8.0 原生窗口函数更可靠。

MySQL 8.0 资源组信息存储在哪里,如何查看已创建的资源组?

资源组元数据存于系统表 information_schema.resource_groups,字段含 RESOURCE_GROUP_NAME、TYPE(USER/SYSTEM)、ENABLED、VCPU_IDS(如 0-1)、THREAD_PRIORITY。默认有 USR_default、SYS_default 两组(绑定全部核,优先级0)。创建 user 级资源组时 thread_priority 须大于 0,system 级用于限制 InnoDB purge/read 等后台线程。

MySQL 8.0 资源组如何在 SQL 层面(HINT)而非运维层面绑定?

除运维用 SET RESOURCE GROUP 绑定线程外,开发层面可在 SQL 加 HINT:SELECT /*+ RESOURCE_GROUP(user_ytt) */ guid FROM t1 GROUP BY LEFT(guid,8) ORDER BY RAND(); 这样该语句自动落在 user_ytt 资源组绑定的 CPU 核上运行,其他请求不受影响。文中 838 万行排序查询在 4 分 46 秒完成且不影响其他请求。

MySQL 8.0 资源组有哪些限制和平台要求?

限制包括:(1) Linux 需开启 CAP_SYS_NICE(systemd 加 AmbientCapabilities=CAP_SYS_NICE);(2) 开启线程池后 RG 失效;(3) FreeBSD/Solaris 上 thread_priority 失效;(4) 目前只能绑定 CPU,不能绑定其他资源(如内存、IO)。文中强调资源组“基本”解决烂 SQL 问题,因不能限制 CPU 以外资源。

MySQL 8.0 资源组(Resource Group)如何使用来限制烂 SQL 占用 CPU?

资源组可将线程绑定到指定 CPU 核。创建:CREATE RESOURCE GROUP user_ytt TYPE=USER VCPU=0-1 THREAD_PRIORITY=19 ENABLE; TYPE=USER 为前台线程,TYPE=SYSTEM 为后台线程。通过 SET RESOURCE GROUP user_ytt FOR 278(线程ID从 performance_schema.threads 取)或在 SQL 加 HINT /*+ RESOURCE_GROUP(user_ytt) */ 绑定。RG 信息存于 information_schema.resource_groups。

MySQL 8.0 通用表表达式(CTE/WITH)解决了什么性能问题?

CTE 通过 WITH 子句定义临时结果集,相比视图在同一条 SQL 中多次访问时只需固化一次(视图会多次固化),减少资源消耗。文中对比视图与 WITH 查询计划,B 比 A 少一次视图固化,且无论访问多少次都仅固化一次。此外 CTE 可替代“临时表不能多次打开”的限制(ERROR 1137 Can’t reopen table),用 WITH 重写即可避免。

MySQL 8.0 通用表表达式(CTE)除了性能,在功能上还有什么价值?

CTE 可解决“临时表不能多次打开”(ERROR 1137 Can’t reopen table: ‘ytt_tmp1’)的老问题:把临时表转为 WITH 表达式后可在同一条 SQL 中多次引用(如子查询里两次取 MAX/MIN)。相比先把临时表固化到磁盘再当普通表访问的传统做法,CTE 在内存中一次固化多次复用,写法更自然、资源更省。

MySQL 8.0 错误日志 JSON 输出中关键字段有哪些,如何用 jq 快速分析?

JSON 日志每行含 log_type、prio(1=Error,2=Warning)、err_code(如12592)、subsystem(如 InnoDB)、msg、time、thread、err_symbol(如 ER_IB_MSG_767)、SQL_state、label。用 jq ‘.msg’ mysqld.log.00.json 可只提取错误信息;结合 log_filter_dragnet 过滤后输出更干净,便于自动化排障。

MySQL 8.0 错误日志的 JSON 输出与过滤如何配置?

安装部件 INSTALL COMPONENT ‘file://component_log_sink_json’; 再 SET GLOBAL log_error_services=‘log_filter_internal; log_sink_json’; 即可同时输出文本和 JSON(mysqld.log.00.json),JSON 含 err_code、subsystem、msg、time 等字段,可用 jq 提取。过滤用 component_log_filter_dragnet,规则如 IF prio>=WARNING THEN drop. 或 throttle 1/60(每60秒仅记一条)。

MySQL 8.0 默认字符集变化对升级有什么影响,如何处理新旧对象字符集不一致?

8.0 默认字符集为 utf8mb4,可能导致旧数据字符集与新建对象不一致。避免方法:在配置文件中将字符集和校验规则显式设为旧版本的值(如 utf8mb4 或原字符集)。若原用 utf8(3字节)而需存4字节生僻字/表情,应整体迁移到 utf8mb4。迁移相关参数 innodb_file_per_table、innodb_large_prefix 也需规划。

MySQL 8.0.16 的 CHECK 约束解决了什么数据质量问题?

此前 MySQL 仅支持实体/域/引用/唯一约束,缺 CHECK 完整性。8.0.16(2019-04-25 GA) 起支持,如 CREATE TABLE person(name varchar(16), age int, CONSTRAINT ck_person_001 CHECK(age>18)),插入不满约束报错 ERROR 3819 Check constraint violated。低版本(如 8.0.15)会直接忽略 CHECK 定义。域完整性(如 int unsigned)无法表达“age>18”这类范围,CHECK 正好补充。

从 5.7 升级到 8.0 时,配置文件哪些不兼容项会导致初始化或启动失败?

主要注意:(1) sql_mode 不能包含 NO_AUTO_CREATE_USER(8.0 已废弃),否则初始化秒级完成但数据目录为空且无报错;(2) 默认认证插件改为 caching_sha2_password(5.7 为 mysql_native_password),低版本客户端可能不兼容;(3) lower_case_table_names 启动时值必须与初始化时一致;(4) 8.0.11 删除了 DB2/MAXDB/MSSQL 等兼容 SQL Mode,使用这些 Mode 的复制会异常。

将 MySQL 字符集从 utf8 迁移到 utf8mb4 有哪些方案及注意事项?

方案一:准备新实例,设 character-set-server=utf8mb4、collation-server=utf8mb4_general_ci、skip-character-set-client-handshake、innodb_large_prefix=ON(允许索引最大3072字节);导出表结构改 utf8→utf8mb4 再导入。方案二:ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4(拷全表、加锁),改库字符集只需改元数据很快。应用的 JDBC url 需设 characterEncoding=utf-8。

用 mysqldump 从 5.7 升级到 8.0 时,NO_AUTO_CREATE_USER 还有哪些坑?

从 5.7.24 和 8.0.13 起,mysqldump 从存储程序定义中删除了 NO_AUTO_CREATE_USER。若用更早版本的 mysqldump 生成的转储文件,必须手动修改删除 NO_AUTO_CREATE_USER,否则导入 8.0 出错。此外若升级到 8.0.3+ 做 in-place 升级,BACKUP_ADMIN 权限会自动授予具 RELOAD 权限用户。

MySQL 8.0 原子 DDL 支持和不支持哪些语句范围?

支持的表相关原子 DDL:库、表空间、表、索引的 CREATE/ALTER/DROP 及 TRUNCATE TABLE;表无关:存储过程、触发器、视图、UDF 的 CREATE/DROP,以及帐户管理(用户/角色 CREATE/ALTER/DROP、GRANT/REVOKE)。不支持:非 InnoDB 引擎表相关 DDL、INSTALL/UNINSTALL PLUGIN 与 COMPONENT、CREATE/ALTER/DROP SERVER。对比 5.7,8.0 中 RENAME 两条表失败不会只改一张。

MySQL 8.0 原子 DDL 是如何实现的?

8.0 将数据字典全部存入 InnoDB 系统表(mysql.ibd),crash recovery 可安全回滚,保障原子性。DDL 分四阶段:准备(写 DDL 日志到隐藏表 mysql.innodb_ddl_log)、执行、提交(提交数据字典事务)、Post-DDL(重放并删除 ddl_log,文件操作放此阶段)。日志类型 FREE/DELETE/RENAME/DROP。可设 innodb_print_ddl_logs=1、log_error_verbosity=3 在错误日志查看。

MySQL 8.0 原子 DDL 的 DDL 日志表 mysql.innodb_ddl_log 结构如何,如何查看?

该隐藏表存于 mysql.ibd,结构含 id(BIGINT 自增)、thread_id、type(FREE/DELETE/RENAME/DROP)、space_id、page_no、index_id、table_id、old_file_path、new_file_path。正常情况 Post-DDL 阶段重放并删除;仅当 DDL 过程故障才保留,重启后重放。普通模式无法直接访问,需 debug 模式;或设 innodb_print_ddl_logs=1、log_error_verbosity=3 在错误日志观察 DDL 过程。

MySQL 8.0 的 GROUPING() 函数如何使用来区分 ROLLUP 汇总行?

GROUP BY … WITH ROLLUP 的高位字段显示为 NULL,若表本身含 NULL 记录则难以区分。GROUPING(col) 返回该列是否为 ROLLUP 结果(是1否0)。多参数时 GROUPING(r1,r2) 等价于 GROUPING(r2)+GROUPING(r1)«1,结果可能为 0/1/3。可置于 SELECT、HAVING(如 HAVING GROUPING(r1)=1 OR GROUPING(r2)=1 仅留汇总行)、ORDER BY 中。

MySQL 8.0 查询重写插件如何利用语句摘要定制改写规则?

在 query_rewrite.rewrite_rules 中,pattern 与 replacement 用 statement_digest_text() 归一化(常量变 ?)。例如将“DELETE FROM p1 WHERE id=1000”改写为“id=-1”,插入规则后 CALL query_rewrite.flush_rewrite_rules(); 生效。执行 delete from p1 where id=20000 会被重写为 id=-20000(show warnings 可见 Note 1105 提示),借此拦截危险删除。

MySQL 8.0 语句摘要函数 statement_digest 与 statement_digest_text 有什么用途?

statement_digest_text() 将 SQL 归一化为摘要文本(数字变 ?,如表名/字段不变才归一类);statement_digest() 用 SHA2 计算摘要哈希值,相同模式语句哈希一致(如3条不同 limit 的语句哈希均为 32744c5…)。可用于 performance_schema/sys.statement_analysis 按 digest 聚合分析,或在查询重写插件 query_rewrite.rewrite_rules 中按摘要定制改写规则。

MySQL 8.0 语句摘要如何与 sys 库 statement_analysis 结合做性能分析?

开启性能字典消费者:CALL sys.ps_setup_enable_consumer(‘statements’); 执行待分析 SQL 后,从 sys.statement_analysis 用 WHERE digest=statement_digest(’…’) 过滤,可看 exec_count、total_latency、rows_examined、lock_latency、rows_sorted 等指标。摘要把不同常量值归为同一类,便于统计某类语句整体表现,比慢日志 grep 更高效。

MySQL 8.0 对 JSON 数组增加了什么范围遍历能力?

8.0 在原有 $[下标]、$[*] 基础上新增范围遍历 $[m to n],如 JSON_EXTRACT(@arr,’$[0 to 3]’) 取 0~3 元素;n 可用保留字 last 表示末位,如 ‘$[0 to last-7]’。文中用此特性将原本需存储过程+JSON_REMOVE 循环的实现简化,直接 JSON_EXTRACT 即可批量提取数组片段,开发更便捷。

MySQL 8.0 的 CUME_DIST() 窗口函数含义及用法?

CUME_DIST() 表示当前行及小于等于当前行值在窗口分区总行数中的累计占比。文中 user1 按 createtime 排序,id=1 对应值 0.2222(小于等于它的有2行/共9行)。配合 window w AS (order by createtime) 使用,常用于计算百分位分布,比手动计数简洁。

MySQL 8.0 窗口函数有哪些典型适用场景?

场景一:计算占比,sum(amount) over() 求总量,各用户 everymoney/总量得 percent;场景二:求每天交易额第一的用户,row_number() over(partition by paydate order by total desc) 编号后取 num=1。8.0 新增窗口函数含 ROW_NUMBER、RANK、DENSE_RANK、CUME_DIST、LAG、LEAD、NTILE、FIRST_VALUE 等,可定义 WINDOW w AS(…) 复用窗口。

MySQL 8.0 窗口函数适用场景中,如何计算“每天交易额第一的用户”并取最终结果?

先子查询按 user、paydate 分组求每日总额 total,再用 row_number() over(partition by paydate order by total desc) 编号;外层包一层 WHERE num=1 即得每天交易额最高用户。文中结果王五(07-01/03/10)、张三(07-14/30)各居首。该写法比自连接/变量更直观,且窗口可命名复用。

MySQL 8.0 通过 caching_sha2_password 认证时,客户端无法获取 RSA 公钥会怎样?

默认服务端不会主动发 RSA 公钥给客户端。客户端要么拷贝服务端 RSA 公钥文件并用 –server-public-key-path 指定,要么连接时加 –get-server-public-key 向服务端请求(后者多一次 C/S 通信,前者在网络可靠前提下更安全)。若两者都没有公钥,基于 RSA 密钥对的密码交换无法进行,连接失败。–server-public-key-path 优先级高于 –get-server-public-key。

MySQL 8.0 默认认证插件 caching_sha2_password 如何使用 RSA 密钥对?

参数 caching_sha2_password_auto_generate_rsa_keys 默认开启,启动时自动生成 RSA 公私钥;也可 mysql_ssl_rsa_setup 手动生成。状态变量 Caching_sha2_password_rsa_public_key 查看公钥。客户端有两种方式获取公钥:拷贝服务端公钥用 –server-public-key-path,或请求获取用 –get-server-public-key(前者更优)。通过该插件访问需加密连接或 RSA 密码交换。

MySQL 8.0 中 create role 与 create user 权限有何区别?

仅授予 CREATE ROLE 权限的用户(如 ytt8)只能 CREATE ROLE,不能 CREATE USER(报错 1227 need CREATE USER privilege);而授予 CREATE USER 权限的用户(如 ytt9)既能 CREATE USER 也能 CREATE ROLE——即 CREATE USER 隐含包含 CREATE ROLE 能力。两者都是创建角色所需的权限,但 CREATE USER 权限范围更广。

MySQL 8.0 角色与用户的关系:用户能否当作角色授权给另一个用户?

可以。普通用户 ytt11 授予 SELECT 后,GRANT ytt11 TO ytt12 即把 ytt11 的权限作为角色赋予 ytt12;show grants for ytt12 显示 GRANT ytt11@% TO ytt12@%,用 SHOW GRANTS FOR ytt12 USING ytt11 可展开具体权限。说明 8.0 中“用户”和“角色”在授权模型上已统一。

MySQL 8.0 角色功能中,一个用户如何拥有多个角色并在会话中切换?

GRANT db_owner,db_datareader,db_datawriter TO ytt4 后 SET DEFAULT ROLE ALL TO ytt4,登录后 current_role() 显示全部角色。会话中可用 SET ROLE db_datareader 切换到只读角色(此时建表报 CREATE command denied),再用 SET ROLE db_owner 恢复。实现同一账号在不同业务场景下的权限隔离。

MySQL 8.0 角色(Role)功能有哪些关键用法?

角色默认不激活,需 GRANT role TO user 后 SET DEFAULT ROLE … TO user(或 SET ROLE 切换当前角色)才能用。一个用户可拥有多角色(SET DEFAULT ROLE ALL)。参数 activate_all_roles_on_login 控制登录自动激活,mandatory_roles 强制所有用户拥有某角色。CREATE USER 隐含 CREATE ROLE 权限;普通用户也可 GRANT user TO other 当角色用;撤销角色用 REVOKE 或 DROP ROLE。

MySQL 8.0 的 TABLE 语句在子查询中使用时有什么约束,举例说明?

TABLE t1 作为子查询内层(如 (r1,r2) IN (TABLE t1))时,内表字段数量必须与外层过滤字段数量一致,否则报错。文中 t1、t2 均为两字段,故 SELECT * FROM t2 WHERE (r1,r2) IN (TABLE t1) 成功;若数量不匹配则出错。TABLE 内部被 MySQL 转换为 SELECT(show warnings 可见 Note 1003 重写信息)。

MySQL 8.0.19 新增的 TABLE 和 VALUES 语句分别有什么用途?

TABLE 语句用于小表全表扫描场景(路由表、配置表、映射表),语法 TABLE t1 [ORDER BY][LIMIT],内部被转换为 SELECT;也可做子查询内层(字段数须一致),如 SELECT * FROM t2 WHERE (r1,r2) IN (TABLE t1)。VALUES 模拟记录集,类似 PG 的 ROW,如 VALUES ROW(1,2,3)、多行 UNION ALL、按列下标 ORDER BY 1,结果列名 COLUMN_0 起,便于快速造数据。

通过 wireshark 抓包看 MySQL 8.0 加密连接,TLS 握手过程是怎样的?

8.0 用 caching_sha2_password 建立 TLS 加密连接(本次算法 DHE-RSA-AES128-GCM-SHA256,client TLSv1.2)。握手:ClientHello(随机数/密码套件)→ServerHello→Certificate(x509证书)→Server Key Exchange(DH参数)→Client Key Exchange(Pre-master secret)→Change Cipher Spec→Encrypted Handshake。之后 Application Data 均为加密流,wireshark 无法直接解密 SQL。

MySQL 8.0 升级讨论中提到 Hash Join 相比 MariaDB 实现有何优势?

MySQL 8.0.18 引入 Hash Join、8.0.19 移除 Block Nested-Loop Join;无索引时优化器直接选 Hash Join,且超过内存可基于磁盘(MariaDB 5.5 的 Hash Join 需手动指定、表大于内存不支持)。当前不足:未利用多线程(优化器并行度弱,仅 COUNT(*) 主键扫描支持并行)。适合报表/风控类分析查询提速。

为什么现在被认为是升级 MySQL 8.0 的好时机?8.0 有哪些不容错过特性?

投票 TOP3:快速加列、MGR、原子 DDL 与 Hash Join(并列)。快速加列(8.0.13 起)秒级完成,默认值初始定义、行变更才更新;原子 DDL 本质将元数据表由 MyISAM 改为 InnoDB;Hash Join 8.0.18 引入、8.0.19 移除 Block Nested-Loop Join,超内存可落盘;MGR 强烈建议用 8.0(网络分区更稳)。8.0 采用小版本快速迭代(8.0.12 GA、8.0.17 clone plugin、8.0.19 隐藏/降序索引)。

升级到 MySQL 8.0 后认证机制变化及兼容方案?

8.0 默认认证插件由 5.7 的 mysql_native_password 变为 caching_sha2_password(文中称 sha_256),低版本客户端可能不识别加密方式导致连接问题。若想业务无感知,可将验证方式设回 native_password 以兼容 5.7。正常按 5.7→8.0 升级方式即可享受 8.0 特性,其余方面影响较小。