那些 MySQL 8.0 中的隐藏特性

在本文中,我想讨论 MySQL 8.0 中的几个相当新的特性,以及一个较老的特性。这些可能是您不知道的次要功能,但值得快速了解一下它们的工作方式以及在某些情况下可能的用途。

作者:Corrado Pandiani

本文来源:Percona 官网博客

  • 爱可生开源社区出品。

与隐藏有关的特性:

  • 隐藏列
  • 生成的隐藏主键
  • 隐藏索引

下面让我们来看看。

隐藏列

8.0.23 新增隐藏列特性。什么是隐藏列?它基本上是一个表的常规列,具有自己的名称和数据类型。它像任何其他常规列一样处理和更新,唯一的区别是对应用程序不可见。换句话说,只有在 SELECT 语句中明确搜索它时,才能访问它;否则,它就像一个不存在的列。

这个定义看起来很奇怪,但如果提供一个这个特性的真实使用案例,一切都应该更清晰。

假设您的应用程序代码中有 SELECT * 查询。作为经验丰富的数据库开发人员,您应该知道这种查询不应存在于任何生产代码中。典型的问题是,当您需要更改表架构,添加或删除列,或者更糟的是在其他列中间添加新列时。抓取到你应用程序变量中的字段位置可能会完全打破应用程序或触发意外的错误行为。这就是您需要避免在应用程序中使用 SELECT * 的原因。

在这种情况下,如果您需要避免更改应用程序代码以匹配新表架构,可以将新列添加为隐藏列,它不会返回给客户端,因为您的查询没有明确搜索它。所以,您的应用程序不会失败或出现奇怪的行为。而这,就是隐藏列的用武之地。

您需要在列定义中使用 INVISIBLE 关键字。当您需要将列设置为可见时,需要使用 VISIBLE 关键字。让我们看一个例子。

我们创建一个表并插入一些行:

mysql> CREATE TABLE articles (id INT UNSIGNED AUTO_INCREMENT,ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,article TEXT,PRIMARY KEY(id)
);
Query OK, 0 rows affected (0.03 sec)mysql> INSERT INTO articles(article) VALUES("This is first article"),("This is second article"),("This is third article");
Query OK, 3 rows affected (0.01 sec)  
Records: 3  Duplicates: 0  Warnings: 0mysql> SELECT * FROM articles;
+----+---------------------------+------------------------------+
| id | ts                  | article                |
+----+---------------------------+------------------------------+
|  1 | 2023-07-28 13:15:03 | This is first article  |
|  2 | 2023-07-28 13:15:03 | This is second article |
|  3 | 2023-07-28 13:15:03 | This is third article  |
+----+---------------------------+------------------------------+

有时,我们决定必须在 ts 列之后向表中添加一个新的字段 title。为了避免我们的应用程序因 SELECT * 和新添加的中间列等情况失效,我们必须将 title 列创建为 INVISIBLE

mysql> ALTER TABLE articles ADD COLUMN title VARCHAR(200) INVISIBLE AFTER ts;
Query OK, 0 rows affected (0.06 sec)  
Records: 0  Duplicates: 0  Warnings: 0

为新列提供一些值:

mysql> UPDATE articles SET title='Title 1' WHERE id=1;
UPDATE articles SET title='Title 2' WHERE id=2; 
UPDATE articles SET title='Title 3' WHERE id=3;

现在看看表架构:

CREATE TABLE `articles` (`id` int unsigned NOT NULL AUTO_INCREMENT,`ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`title` varchar(200) DEFAULT NULL /*!80023 INVISIBLE */,`article` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

你可以看到,该列被正确地标记了 INVISIBLE 关键字。

再试一次 SELECT *

mysql> SELECT * FROM articles;
+----+---------------------------+------------------------------+
| id | ts                  | article                |
+----+---------------------------+------------------------------+
|  1 | 2023-07-28 13:15:03 | This is first article  |
|  2 | 2023-07-28 13:15:03 | This is second article |
|  3 | 2023-07-28 13:15:03 | This is third article  |
+----+---------------------------+------------------------------+

你看,该列没有返回。这允许 schema 改变后查询不会失败。

如果你想看 title,你必须明确寻址该字段:

mysql> SELECT id, ts, title, article FROM articles;
+----+---------------------------+-----------+------------------------------+
| id | ts                  | title   | article                |
+----+---------------------------+-----------+------------------------------+
|  1 | 2023-07-28 13:15:03 | Title 1 | This is first article  |
|  2 | 2023-07-28 13:15:03 | Title 2 | This is second article |
|  3 | 2023-07-28 13:15:03 | Title 3 | This is third article  |
+----+---------------------------+-----------+------------------------------+

使用以下 DDL 将列设置为可见:

mysql> ALTER TABLE articles MODIFY COLUMN title varchar(200) VISIBLE;

记住,隐藏列像任何其他常规列一样处理,所以您可以随时读取和更新它们。关于隐形性的元数据在 information_schema 中可用,INVISIBLE/VISIBLE 关键字在 binlog 中保留,以便正确复制所有更改。

生成的隐藏主键

这个特性在 MySQL 8.0.30 开始提供。生成的隐藏主键(GIPK)是一种特殊的隐藏列,仅适用于 InnoDB 表。

没有主键的情况下创建 InnoDB 表,往往不是一个好的选择。我们强烈建议您的表中始终创建显式主键。您可能还知道,如果您不提供主键,InnoDB 会创建一个隐藏的主键,但是 GIPK 提供的新特性使主键可以变得可用和最后可见。相反,隐含创建的早期隐藏主键既不能成为可用的也不能成为可见的。

该功能对于强制缺乏经验的用户的 InnoDB 表都具有显式主键很有用,即使是隐藏的。

让我们看看它是如何工作的。

默认情况下,此功能被禁用,因此 MySQL 将继续像过去一样运行。要启用 GIPK,您必须设置以下动态系统变量(它具有全局和会话作用域):

mysql> SET [PERSIST] sql_generate_invisible_primary_key=ON; 

现在在不指定显式主键的情况下创建一个表:

mysql> CREATE TABLE customer(name VARCHAR(50));
Query OK, 0 rows affected (0.03 sec)

检查模式:

mysql> SHOW CREATE TABLE customerG
*************************** 1. row ***************************Table: customer  
Create Table: CREATE TABLE `customer` (`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,`name` varchar(50) DEFAULT NULL,PRIMARY KEY (`my_row_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

名为 my_row_id 的隐藏主键已经自动创建。

注意:

  • GIPK 的名称始终为 my_row_id。您不能在表中有相同名称的列。
  • GIPK 的数据类型始终为使用 AUTO_INCREMENT 的 BIGINT UNSIGNED。

有趣的是,您可以在查询中使用主键并在明确寻址时看到它,就像描述的隐藏列一样。

mysql> INSERT INTO customer VALUES('Tim'),('Rob'),('Bob');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0mysql> SELECT my_row_id, name FROM customer;
+--------------+-------+
| my_row_id | name |
+--------------+-------+
|         1 |  Tim |
|         2 |  Rob |
|         3 |  Bob |
+--------------+-------+
3 rows in set (0.00 sec)mysql> SELECT my_row_id, name FROM customer WHERE my_row_id=2;
+--------------+-------+
| my_row_id | name |
+--------------+-------+
|         2 |  Rob |
+--------------+-------+
1 row in set (0.00 sec)

很显然。如果您执行 SELECT *,主键不会被返回:

mysql> SELECT * FROM customer WHERE my_row_id=2;
+-------+
| name |
+-------+
| Rob  |
+-------+

在某些时候,您最终可以决定使其可见,并在需要时更改名称:

mysql> ALTER TABLE customer MODIFY `my_row_id` bigint unsigned not null auto_increment VISIBLE;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> SHOW CREATE TABLE customerG  
*************************** 1. row ***************************Table: customer
Create Table: CREATE TABLE `customer` (`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,PRIMARY KEY (`my_row_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

隐藏索引

为了完成隐形事物的概述,我们也来讨论一下隐藏索引。这是最古老的隐形特性,在 MySQL 8.0 的第一个版本中就引入了。

您可以使索引对优化器不可见,以便测试如果该索引不存在,查询的性能会如何。不过,当索引不可见时,在针对表执行任何 DML 语句(INSERT、UPDATE、DELETE、REPLACE)时,它仍会得到更新。

您可以使用以下语句将索引设置为不可见和再次可见:

ALTER TABLE mytable ALTER INDEX my_idx INVISIBLE;
ALTER TABLE mytable ALTER INDEX my_idx VISIBLE;

隐藏索引可以测试在不考虑它的情况下查询的执行计划。最大的优点是您不需要删除索引。请记住,索引删除几乎是瞬间完成的,但重建索引则不然。根据表的大小,重建索引可能需要大量时间并过载服务器。另一种选择是,您也可以使用 IGNORE INDEX() 索引提示,但在这种情况下,您可能会被迫在应用程序代码中的许多查询上添加索引提示。将索引设置为不可见将允许您在很短的时间内开始测试查询。并且您可以随时轻松地将其设置回可见,而不会丢失任何更新。

注意:

  • 主键(PRIMARY Key)不能隐藏
  • UNIQUE 索引可以隐藏,但仍会执行唯一性检查
  • 有关索引不可见性的信息在 information_schema 中可用
  • 索引不可见性会被正确复制

总结

从我的角度来看,你不应该使用隐藏列,因为最佳实践是不应在任何应用中部署SELECT * 查询。不过,在某些紧急情况下,此功能可能非常有用,可以飞快地解决问题。但是之后要记住修复你的代码并将隐藏列设置为可见会更好。

对 GIPK 来说,情况也差不多。只要记住为表提供显式主键,就不需要此功能。不过,它可以帮助一个创建时没有主键的表拥有一个适当的主键,这个主键可以方便地被使用和变得可见。

关于隐藏索引,这是一个非常简单的功能,在测试时非常有用,特别是在可能使用多个索引,和不确定优化器是否选择了最佳执行计划的情况中。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

爱可生开源社区的 SQLE 是一款面向数据库使用者和管理者,支持多场景审核,支持标准化上线流程,原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。

SQLE 获取

类型地址
版本库https://github.com/actiontech/sqle
文档https://actiontech.github.io/sqle-docs/
发布信息https://github.com/actiontech/sqle/releases
数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/26951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电源控制--品质因素Q值全解

什么是品质因素Q值? 在电源控制中,品质因素 Q 值通常用于描述电源滤波器的性能。电源滤波器用于减小电源中的噪声和干扰,以提供干净稳定的电源供应给电子设备。 品质因素 Q 值在电源滤波器中表示滤波器的带宽和中心频率之比,用于…

IP提取器对比器

需求: 一个html 页面 ,有两个输入框 第一个输入框输入文本中包含多个ip,输入的ip是不规则的,需要使用正则表达式提取出 输入文本的ip地址 , 然后在第二个输入框中输入内容,并提取出内容的ip ,如…

Spark 内存管理之 MemoryConsumer

MemoryConsumer 是内存的使用者,如 sort, shuffle。MemoryConsumer 的 spill 方法是抽象方法,由子类提供。 MemoryConsumer 的字段和构造方法如下: public abstract class MemoryConsumer {protected final TaskMemoryManager taskMemoryMan…

Linux进程间通信--msgsnd函数的作用

msgsnd函数用于将消息发送到消息队列中。它的原型如下: int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数解释: msqid:消息队列标识符,由msgget函数返回。msgp:指向要发送的消息的指针&…

改变vue循环生成的盒子样式,给点击的某一个盒子添加不同的样式

1.给盒子添加动态属性:class"[index isActive?active-box:choose-box]" <div v-for"(item,index) in zyList" :key"item.sid" :class"[index isActive?active-box:choose-box]" click"getKmList(item,index)"…

大数据开发的学习路线是什么样的

大数据技术的体系庞大且复杂&#xff0c;每年都会涌现出大量新的技术&#xff0c;目前大数据行业所涉及到的核心技术主要就是&#xff1a;数据采集、数据存储、数据清洗、数据查询分析和数据可视化。 学习大数据需要掌握什么语言基础&#xff1f; 1、Java基础 大数据框架90%以…

什么是OCR?OCR技术详解

光学字符识别(Optical Character Recognition)简称为“OCR”。ORC是指对包含文本资料的图像文件进行分析识别处理&#xff0c;获取文字及版面信息的技术。 一般包括以下几个过程&#xff1a; 1.图像输入 针对不同格式的图像&#xff0c;有着不同的存储格式和压缩方式。目前&…

Elastic:linux设置elasticsearch、kibana开机自启

0. 引言 每次启动服务器都要手动启动es服务&#xff0c;相当之不方便&#xff0c;为此&#xff0c;书写一个脚本&#xff0c;实现es、kibana的开机自启 1. 原理 首先任何服务要实现开机自启&#xff0c;都可分为如下三步&#xff1a; 1、在/etc/init.d目录下创建启动、关闭服…

C#设计模式(15)命令模式(Command Pattern)

命令模式&#xff08;Command Pattern&#xff09; 命令模式是一种数据驱动的设计模式&#xff0c;属于行为型模式类别。请求被包装在一个对象中作为命令&#xff0c;并传递给调用对象。调用对象寻找可以处理该命令的合适对象&#xff0c;并将命令传递给相应的对象&#xff0c…

海康威视摄像头配置RTSP协议访问、onvif协议接入、二次开发SDK接入

一、准备工作 (1)拿到摄像头之后,将摄像头电源线插好,再将网线插入到路由器上。 (2)将自己的笔记本电脑也连接到路由器网络,与摄像头出在同一个局域网。 二、配置摄像头 2.1 激活方式选择 第一次使用设备需要激活,在进行配置。 最简单,最方便的方式是选择浏览器激…

uniapp创建项目入门【详细】

大家在学习vue和微信小程序之后&#xff0c;就可以开始来学习uniapp了&#xff0c;在uniapp中&#xff0c;一套代码可以跨越所有的平台&#xff0c;可以很方便的维护。接下来我们先来学习如何创建uinapp的项目 一、uniapp的创建需求 大家只要会vue和微信小程序的基础来学习unia…

在CentOS7安装部署GitLab服务

CentOS 7 安装 Gitlab 官方安装教程&#xff1a;https://about.gitlab.com/install/ 参考安装教程&#xff1a;https://developer.aliyun.com/article/74395 安装配置 Step1&#xff1a;配置yum源 vim /etc/yum.repos.d/gitlab-ce.repo存入以下内容&#xff1a; [gitlab-c…

目标分割后 opencv 轮廓骨架计算

opencv获取轮廓 contours, hierarchy = cv2.findContours(mask_i, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)获取分割图像的骨架 # 中轴变换 得到裂缝的骨架使用 skimage.morphology.skeletonize 函数对二值化图像进行骨架提取。skeleton = skeletonize(mask_i, method

浅析 String

浅析String 一、创建字符串二、字符串与常量池三、字符串的不可变性四、字符串的拼接五、StringBuilder和StringBuffer 一、创建字符串 //三种常用的构造字符串的方式public static void main(String[] args) {String str1 "hello";String str2 new String("w…

恢复swp文件

swp文件_.swp文件_luminous_you的博客-CSDN博客 三、恢复源文件 正常URL:xxx/m.php 则尝试URL:xxx/.m.php.swp下载.swp文件代码 假设你的swp文件叫’.m.php.swp’ 可用带-r参数编辑#vi -r m.php 然后wq保存即可

图论 <最短路问题>模板

图论 <最短路问题> 有向图 1.邻接矩阵&#xff0c;稠密图 2.邻接表 &#xff08;常用&#xff09;单链表&#xff0c;每一个点都有一个单链表 &#xff0c;插入一般在头的地方插&#xff0c; 图的邻接表的存储方式 树的深度优先遍历 特殊的深度优先搜索&#xff0c…

Python检查端口是否打开(七种方法)

sock.connect_ex 使用socket模块的connect_ex来判断端口是否打开&#xff0c;如果返回值是0表示连接成功&#xff0c;端口打开&#xff0c;否则端口关闭。 import socketdef check_port(ip, port): sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeo…

Python导出SqlServerl数据字典为excel

sql代码 SELECTtableName D.name ,tableIntroduce isnull(F.value, ),sort A.colorder,fieldName A.name,catogary B.name,bytes A.Length,lengths COLUMNPROPERTY(A.id, A.name, PRECISION),scales isnull(COLUMNPROPERTY(A.id, A.name, Scale), 0),isOrNotNull Cas…

springboot 对接 minio 分布式文件系统

1. minio介绍 Minio 是一个基于Go语言的对象存储服务。它实现了大部分亚马逊S3云存储服务接口&#xff0c;可以看做是是S3的开源版本&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等&#xff0c;而一个对象…

Mac OS键盘常用快捷键

图形按键⌘Command 键⌃Control 键⌥Option 键⇧Shift 键⇪Caps Lockfn功能键 常用快捷键剪切、拷贝和粘贴 您可以在大多数 app 中使用这些快捷键来剪切、拷贝或粘贴选中的项目。其中包括文本、图片、音乐等等。您甚至可以在 Finder 中拷贝和粘贴文件&#xff0c;来将文件拷贝到…