MySQL进阶之(四)InnoDB数据存储结构之行格式

news2024/11/24 5:01:07

四、InnoDB数据存储结构之行格式

  • 4.1 行格式的语法
  • 4.2 COMPACT 行格式
    • 4.2.1 记录的额外信息
      • 01、变长字段长度列表
      • 02、NULL 值列表
      • 03、记录头信息
    • 4.2.2 记录的真实数据
  • 4.3 Dynamic 和 Compressed 行格式
    • 4.3.1 字段的长度限制
    • 4.3.2 行溢出
    • 4.3.3 Dynamic 和 Compressed 行格式
  • 4.4 Redundant 行格式
    • 4.4.1 字段长度偏移列表
    • 4.4.2 记录头信息(record header)
    • 4.4.3 NULL 值处理

我们平时的数据都是以行记录为单位向表中插入数据的,这些记录在磁盘上的存放形式也被称为 行格式或者 记录格式。设计 InnoDB 存储引擎的大叔到现在为止设计了 4 中不同类型的行格式,分别是 COMPACT、REDUNDANT、DYNAMIC 和 COMPRESSED。随着时间的推移,它们可能会设计出更多的行格式,但是不管怎么变,这些行格式在原理上大体都是相同的。
——摘自《MySQL 是怎样运行的》

4.1 行格式的语法

我们可以在创建或者修改表的语句中指定记录所使用的行格式:

# 创建表时指定行格式
CREATE TABLE 表名(列的信息) ROW_FORMAT = 行格式名称
# 修改表的行格式
ALTER TABLE 表名 ROW_FORMAT = 行格式名称

4.2 COMPACT 行格式

COMPACT 表示紧凑的,在 MySQL 5.1 版本中,默认设置为 COMPACT 行格式。

一条完整的记录可以分为记录的额外信息记录的真实数据两大部分:
在这里插入图片描述

4.2.1 记录的额外信息

这部分信息时服务器为了更好地管理记录而不得不额外添加的一些信息。这些额外的信息分为三部分,分别是变长字段长度列表NULL 值列表记录头信息

01、变长字段长度列表

MySQL 支持一些变长的数据类型,比如 varchar(M)、varbinary(M)、text 类型、blob 类型,这些数据类型修饰列称为变长字段变长字段中存储多少字节的数据不是固定的,所以我们在存储真实数据的时候,需要顺便把这些数据占用的字节数也存起来。

也就是说,这些变长字段占用的存储空间分为两部分:

  • 真正的数据内容;
  • 该数据占用的字节数。

在 Compact 行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,且各变长字段的真实数据占用的字节数按照列的顺序逆序存放。

比如,创建一张表:

create table record_test_table(
  col1 varchar(8),
  col2 varchar(8) not null,
  col3 vhar(8),
  col4 varchar(8)
) charset=ascii row_format=Compact

并向表里插入数据:

insert into record_test_table(col1, col2, col3, col4)
values
('zhangsan', 'lisi', 'wangwu', 'songhk'),
('tong', 'chen', NULL, NULL);

因为 record_test_table 表中 col1、col2、col4 列都是 varchar(8) 类型的,所以这三个列的值的长度都会被存储在记录开头处。由于使用的是 ascii 字符集,所以每个字符只需要 1 个字节来进行编码:
在这里插入图片描述
又因为这些长度值需要按照列的顺序逆序存放,所以最后变长字段长度列表的字节串用十六进制表示的效果就是:06 04 08。

在这里插入图片描述

小贴士:并不是所有记录都有这个变长字段长度列表部分,如果表中所有的列都不是变长的数据类型或者所有列的值都是 NULL 的话,就不需要有变长字段长度列表(不冗余存储,节省存储空间)了。

02、NULL 值列表

一条记录中的某些列可能存储 NULL 值,如果把这些 NULL 值都放到 “记录的真实数据” 中存储会很占地方。所以,COMPACT 行格式把一条记录中值为 NULL 的列统一管理起来,存储到 NULL 值列表中。

为什么要定义 NULL 值列表呢?

之所以要存储 NULL 值,是因为数据都是需要对齐的,如果没有标注出来 NULL 值的位置,就有可能在查询数据的时候出现混乱的情况。如果使用一个特殊符号来代替 NULL 值放到对应的位置,虽然可以达到效果,但是大量的 NULL 值列会严重浪费空间,所以干脆就直接在行数据的头部开辟出一块空间,专门用来记录该行哪些数据是非空数据,哪些是空数据

⭐ 规定

将每个允许存储 NULL 的列对应一个二进制位,二进制位按照列的顺序逆序存放,格式如下:

  • 二进制位为 1 时,代表该列的值为 NULL
  • 二进制位为 0 时,代表该列的值不为 NULL

举个例子:字段 a、b、c,其中 a 是主键,在某一行中存储的数依次是 a = 1,b = null,c = 2。那么 COMPACT 行格式中的 NULL 值列表中存储的是:01。第一个 0 表示 c 的值不为 null,第二个 1 表示 b 是 null。这里需要注意以下,之所以没有 a 的值,是因为数据库会自动跳过主键,因为主键肯定是非 null 且唯一的,在 null 值列表的数据中就会自动跳过主键

record_test_table 的两条记录的 NULL 值列表为:

# 这里是上文中插入的两条数据
insert into record_test_table(col1, col2, col3, col4)
values
('zhangsan', 'lisi', 'wangwu', 'songhk'),
('tong', 'chen', NULL, NULL);

在这里插入图片描述

这样我们就可以回答问题了:MySQL 中的 NULL 值是怎么存储的?
答:NULL 值是由 NULL 值列表记录的,用列的二进制位逆序表示每行记录中的每一列是否为 NULL 值,0 代表不为 NULL,1 代表为 NULL 值。

假设现有一张表,其中有 4 个字段:col1、col2、col3、col4。向其插入一条记录:‘a’, NULL, NULL, ‘dd’,那么 NULL 值列表使用二进制位表示为:0 1 1 0,转化成十进制就是 06。

03、记录头信息

除了变长字段长度列表、NULL 值列表之外,还有一个记录头信息的部分,它是由固定的 5 字节组成,用于描述一些属性的。5 个字节也就是 40 个二进制位,不同的位代表不同的属性:
在这里插入图片描述
在这里插入图片描述
其中,重点来说几个属性。

属性一、delete_mask(删除标记)

这个属性标记着当前记录是否被删除,占用 1 个二进制位:

  • 值为 0:代表记录并没有被删除
  • 值为 1:代表记录被删除掉了

被删除的记录为什么还在页中存储呢?

这些被删除的记录不会从磁盘上移除,是因为一旦移除,其他的记录还需要在磁盘上重新排列,这会带来性能消耗

尤其是对聚簇索引的叶子节点来说,假设移除的是主键值为 1 的记录,那么整个聚簇索引的叶子节点都会因为这一条记录的删除全部重新排序,显然这样是不合适的。

所以,只是将这些删除的记录打一个删除标记,以区分正常记录和被删除的记录,所有被删除的记录会组成一个垃圾链表,它们所占用的空间被称为可重用空间,之后如果有新记录插入到表中时,可能会覆盖掉(复用)被删除的记录占用的存储空间。

这里需要注意:将 delete_flag 属性设置为 1 和将被删除的记录加入到垃圾链表中其实是分为两个阶段。

属性二、min_rec_mask(非叶子节点最小记录标记)

B+ 树的每层非叶子节点中的最小记录都会添加该标记,min_rec_mask 值为 1。如果我们自己插入的四条记录的 min_rec_mask 值都是 0,意味着它们都不是 B+ 树的非叶子节点中的最小记录。

属性三、record_type(记录类型)

这个属性表示当前记录的类型,一共有 4 种类型的记录:

  • 0:普通记录
  • 1:B+ 树非叶节点记录
  • 2:最小记录
  • 3:最大记录

再回过头来看:数据页结构和索引结构就可以理解当时的图中为什么表示的 record_type 值不一样了。

heap_no(在页中的相对位置)

这个属性表示当前记录在本页中的位置(设计 InnoDB 的大叔把记录一条一条亲密无间排列的结构称为堆,这个属性也表示在堆中的相对位置)

其中,值为 0 和 1 的记录分别代表最小和最大记录,这两条记录并不是我们自己插入的,所以有时候也称为伪记录或虚拟记录。

n_owned(每行记录数)

页目录中会将所有的记录分成若干个组,每个组中的最后一条记录的头信息中会存储该组一共有多少条记录,来作为 n_owned 字段的值,而其他记录的 n_owned 值都是 0。

next_record(记录的相对位置)

它表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量

假设第一条记录的 next_record 值为 32,意味着从第一条记录的真实数据的地址处向后找 32 个字节就是下一条记录的真实数据。

注意:下一条记录指得并不是按照我们插入顺序的下一条记录,而是按照主键值由小到大的顺序的下一条记录

并且,InnoDB 底层规定 Infimum 记录(最小记录)的下一条记录就是当前页中主键值最小的记录,而当前页中主键值最大的记录指向的下一条记录就是 Supremum 记录(最大记录)。用箭头指向代替地址偏移量来表示 next_record:
在这里插入图片描述
下面来分别演示一下删除一条记录的操作增加一条记录的操作

⭐ 删除一条记录的操作

根据上图所示,假设删除第 2 条记录:

# 删除主键值为2的记录
delete from page_demo where c1 = 2;

删除后,整个链表也会跟着变化:

  1. 把第二条记录的 delete_mask 值设置为 1,而并没有从存储空间中移除;
  2. 把第二条记录的 next_record 值设置为 0,意味着没有下一条记录了;
  3. 第一条记录的 next_record 指向第三条记录;
  4. 最大记录的 n_owned 值从 5 变成了 4。
    在这里插入图片描述

⭐ 增加一条记录的操作

在 “删除一条记录的操作” 中,主键值为 2 的记录被删除了(变成了垃圾链表),但是存储空间并没有被回收。现在要把这条数据再次插入:

# 新增主键值为2的记录
insert into page_demo values(2, 200, 'tong');

新插入的数据,因为指定了主键值为 2,所以按照聚簇索引结构这条记录会按照顺序插入原来第 2 条记录的位置,因为原来被删除的第 2 条记录并没有被真实删除,仍然占有空间,所以这次新插入的数据会复用原有的空间。链表也会发生变化:

  1. 第 2 条记录的 delete_mask 的值变为 0;
  2. 第 2 条记录的 next_record 的值变为 32;
  3. 第 1 条记录的 next_record 指向第 2 条记录,第 2 条记录的 next_record 指向第 3 条记录;
  4. 最大记录的 n_owned的值从 4 => 5。
    在这里插入图片描述

所以,不论我们怎么对页中的记录做增删改操作,InnoDB 始终会维护一条记录的单链表,链表中的各个节点是按照主键值由小到大的顺序连接起来的。

4.2.2 记录的真实数据

记录的真实数据,除了我们自定义的列的数据之外,MySQL 会为每个记录默认地添加一些列(隐藏列):

列名是否必须占用空间描述
DB_ROW_ID6字节行ID,唯一标识一条记录
DB_TRX_ID6字节事务ID
DB_ROLL_PTR7字节回滚指针

为了方便看,就把它们都写成小写的:row_id、transaction_id、roll_pointer。

在 InnoDB 表中,InnoDB 表的主键生成策略是这样的:

  1. 优先使用用户自定义的主键作为主键;
  2. 如果用户没有定义主键,则选取一个不允许存储 NULL 值的 UNIQUE 键作为主键;
  3. 如果表中连不允许存储 NULL 值的 UNIQUE 键都没有定义,则会为表默认添加一个名为 row_id 的隐藏列作为主键。

举个例子:

现创建一张表 mytest:

create table mytest(
  col1 varchar(10),
  col2 varchar(10),
  col3 char(10),
  col4 varchar(10)
)engine=innodb charset=latin1 row_format=compact

并向表中插入三条数据:

insert into mytest values
('a', 'bb', 'bb', 'ccc'),
('d', 'ee', 'ee', 'fff'),
('d', NULL, NULL, 'fff');

找到存储文件 mytest.idb 的位置,用 notepad++ dakai,建议安装一个解析插件,将乱码文件解析成十进制的数据格式:
在这里插入图片描述
在这里插入图片描述
解析第一行记录如下:
由于 col3 列是定长,所以不计入变长字段长度列表中。
在这里插入图片描述
第二行的数据同第一行,这里就不一一列举了。

第三行的数据中有 NULL 值,所以在存储上与第一行、第二行有些差异:
在这里插入图片描述

至于 transaction_id 和 roll_pointer,暂时还没学到哩,等学到时候会做笔记的呀~

4.3 Dynamic 和 Compressed 行格式

4.3.1 字段的长度限制

char 与 varchar 的区别如下:
在这里插入图片描述
也就是说,一个 varchar 类型的字段,最大容量为 65535 个字节。

现在已经存在了一张表,分别查看 MySQL 8.0.26 版本和 MySQL 5.7.34 版本的默认字符集:
在这里插入图片描述
在这里插入图片描述
由此可见,MySQL 8.0.26 字符集默认采用 utf8mb4,MySQL 5.7.34 字符集默认采用 utf8。这两者的区别就是:

  1. utf8:使用 3 个字节表示字符;
  2. utf8mb4:使用 4 个字节表示字符,可以存储一些 emoji 表情等。

说明:统一采用 MySQL 8.0.26 版本来进行接下来的操作。

采用默认字符集 utf8mb4
在这里插入图片描述

报错提示:字段长度最大不能超过 16383,因为 8.0.26 版本默认字符集为 utf8mb4,也就是说,一个字符等于 4 个字节,那么,16383 * 4 = 65532,还差 3 个字节才等于 65535。反过来,65535 除以 4 结果等于 1633.75,由于字段长度不能带小数,将其四舍五入改为 16384:
在这里插入图片描述
显然还是不能超过 16383 的,所以字符集 utf8mb4 允许的最大长度为 16382

那么,那 3 个字节跑哪里了呢?

16383 * 4 = 65532,65535 - 65532 = 3。实际上,每一行记录除了存储真实数据之外,还有记录的额外信息中默认会有变长字段长度列表(2 字节)和 NULL 值列表(1 字节)。所以,如果该 varchar 类型的的列没有 NOT NULL 属性,每一行记录都会默认空出来 3 个字节:存储变长字段长度列表和 NULL 值的标识,实际最多只能存储 65532 个字节的数据。

采用字符集 utf8

由上文可知,需要预留 3 个字节:65535 - 3 = 65532,65532 / 3 = 21844。

重复上述验证步骤:
在这里插入图片描述
由此可知,字符集 utf8 字段的最大长度限制为 21844

采用 ascii 字符集

由上述推断可知,ascii 字符集允许存储字段的最大长度为 65532

4.3.2 行溢出

根据上文所说的单个字段的最大长度根据不同的字符集,会有不同的限制,8.0.26 默认采用 utf8mb4字符集(4 个字节表示一个字符),最大容量为 65532 字节。

而 InnoDB 中一个数据页的大小是 16 KB,16 * 1024 = 16386 个字节,也就是说,一个 varchar 的容量远远大于一个数据页的大小,这样就可能出现一个页存储不下一行记录的情况,这种情况就叫做行溢出

在 Compact 和 Redundant 行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据(768 个前缀字节),把剩余的数据分散存储在其他的页中,这叫作分页存储

然后记录的真实数据处用 20 个字节存储指向这些分散页的地址(这 20 个字节中还包括存储了分散在各个页中的真实数据占用的字节数),从而可以找到剩余数据所在的页,这称为页的扩展,如下图所示:
在这里插入图片描述

4.3.3 Dynamic 和 Compressed 行格式

在MySQL 8.0中,默认行格式就是 Dynamic,Dynamic、Compressed 行格式和 Compact 行格式类似,只不过在处理行溢出数据时方式不同:

  • Compact 和 Redundant 两种格式会在记录的真实数据处存储一部分数据(存放768个前缀字节)。

  • Compressed 和 Dynamic 两种行格式不会在记录的真实数据处存储列真实数据的前 768 字节,而是把所有的数据都存储到溢出页中,只在记录的真实数据处存储指向这些溢出页的地址(20 字节),实际的数据都存放在 Off Page(溢出页)中:
    在这里插入图片描述

Compressed 和 Dynamic 行格式的区别:Compressed 行格式在 Dynamic 的基础上优化了一层,存储在其中的行数据会以 zlib 的算法进行压缩,因此对于 BLOB、TEXT、VARCHAR 这类大长度类型的数据能够进行非常有效的存储。

4.4 Redundant 行格式

Redundant 是 MySQL5.0 版本之前 InnoDB 的行记录存储格式,MySQL 5.0 支持 Redundant 是为了兼容之前版本的页格式。

我们可以直接修改表的行格式为 Redundant:

alter table record_test_table row_rormat=Redundant;

Redundant 行格式存储格式:在这里插入图片描述

对比 Compact 行格式主要有两大处不同:

  1. Compact 是变长字段长度列表,Redundant 是字段长度偏移列表。
  2. Compact 有 NULL 值列表,Redundant 没有 NULL 值列表。

4.4.1 字段长度偏移列表

为什么说 Redundant 行格式会有冗余说法?

因为 Redundant 行格式的字段长度偏移列表会将该行记录中所有列(包括隐藏列)的长度信息都按照逆序存储起来。

偏移两个字,意味着 Redundant 行格式计算列值的长度的方式不像 Compact 行格式那么直观,它是采用两个相邻数值的差值来计算各个列值的长度

比如第一行记录的字段长度偏移列表(逆序)是:

2B 25 1F 1B 13 0C 06

因为它是按照逆序排列的,所以按照顺序排列就是:

06 0C 13 1B 1F 25 2B

可以看出有三个隐藏列和四个字段列。

按照两个相邻数值的差值来计算各个字段列值的长度的如下表所示:

在这里插入图片描述

4.4.2 记录头信息(record header)

不同于 Compact 行格式,Redundant 行格式中的记录头信息固定占用 6 个字节(48 位),每位的含义如下:

在这里插入图片描述
与 Compact 行格式的记录头信息对比来看,有两处不同:

  1. Redundant 行格式多了 n_field 和 1byte_offs_flag 这两个属性。
  2. Redundant 行格式没有 record_type 这个属性。

其中两个属性的含义:

  • n_field 代表一行中列的数量,占用 10 位,所以 MySQL5.0 之前的版本最多只能包含 1023 个列。

  • 1byte_offs_flags 属性定义了字段长度偏移列表占用 1 个字节,还是 2 个字节(使用 127 作为分界点是因为:127 二进制表示为 01111111,第一位为 NULL 比特位,用来标记是否为 NULL)。
    当记录的真实数据占用的字节数不大于 127 时,占用 1 字节;
    当记录的真实数据占用的字节数大于 127,但不大于 32767 时,占用 2 字节;
    当记录的真实数据大于 32767 时,这部分的数据被存放到溢出页中,使用 2 字节来存储梅格列对应的偏移量。

4.4.3 NULL 值处理

因为 Redundant 行格式没有 NULL 值列表,所以在字段长度偏移列表中对各列对应的偏移量做了一些特殊处理:将列对应的偏移量值的第一个比特位作为是否为 NULL 的依据,该比特位也可以称之为 NULL 比特位

也就是说,在解析一条记录的某个列时,首先看一下该列对应的偏移量的 NULL 比特位是否为 1,如果为 1,那么该列的值就是 NULL,否则就不是 NULL。

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

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

相关文章

java工程师面试突击第二季分布式,Java视频

一. 什么是架构和架构本质 在软件行业,对于什么是架构,都有很多的争论,每个人都有自己的理解。 此君说的架构和彼君理解的架构未必是一回事。因此我们在讨论架构之前,我们先讨论架构的概念定义,概念是人认识这个世界的…

VMwareWorkstation17.0虚拟机搭建WindowsME虚拟机(完整安装步骤详细图文教程)

VMwareWorkstation17.0虚拟机搭建WindowsME虚拟机(完整安装步骤详细图文教程) 一、Windows ME安装准备工作3.1 Windows ME下载地址3.2 DOS软盘版下载地址3.3 UltraISO 4.用VMware虚拟模仿当年的电脑配置4.1 新建虚拟机4.2 类型配置4.3 类型配置4.4 选择版…

1、MQ_介绍、优缺点、类型等

MQ介绍 1. MQ概述 MQ(Message Queue):消息队列,是基础数据结构中FIFO(first in first out)的一种数据结构。一般用来解决流量削峰、应用解耦、异步处理等问题,实现高性能,高可用&a…

NOC2023软件创意编程(学而思赛道)python小高组复赛真题

目录 下载原文档打印做题: 软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认…

基于java springboot+VUE疫情防疫系统系统前后端分离设计和实现

基于java springbootVUE疫情防疫系统系统前后端分离设计和实现 博主介绍:5年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言…

K8s Pod 进阶

目录 资源限制 Pod 和容器的资源请求和限制 CPU 资源单位 内存资源单位 示例1 示例2 重启策略(restartPolicy) 示例 健康检查 探针的三种规则 Probe支持三种检查方法 示例1:exec方式 示例2:httpGet方式 示例3&…

C++--调整数组顺序使奇数位于偶数前面

题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。 方法一: …

第三届国际亲子游泳学术峰会,麒小佑为亲游行业提供健康解决方案

第三届国际亲子游泳学术峰会大合影 2024年2月26—28日,第三届国际亲子游泳学术峰会在中国青岛成功召开。 第三届国际亲子游泳学术峰会是中国婴幼游泳行业最高标准的学术性会议,由亲游圈主办,旨在为本行业搭建一个高端圈层,帮助机…

保留数据的重装系统教程!(win10系统)

上车警告!!! 本教程无需思考,跟着操作一步一步来就能完成系统的重装。原理是将C盘系统重装,其他盘符数据保存。适用于系统盘重装数据或更改系统版本。 重要提示!!! C盘有重要学习资…

18个惊艳的可视化大屏(第18辑):数字资产场景

hello,我是贝格前端工场,本次分享可视化大屏在数字资产领域的应用,喜欢文章的别忘点赞关注,文章底部也有其他行业的案例,有需求您说话(可私信)。 数字资产可视化大屏可以应用于各种场景&#x…

从零学习Linux操作系统 第三十一部分 ansible常用模块介绍

一、ansible运行模块的两种方式 Ad-Hoc方式 ##利用ansible命令直接完成管理,主要用于临时命令使用场景 playbook方式 ##ansible脚本,主要用于大型项目场景,需要前期的规划,相当于shell当中的脚本 二、如何查看模块帮助 ansible…

重磅:2024广州国际酒店工程照明展览会

2024广州国际酒店工程照明展览会 Guangzhou international hotel engineering lighting exhibition 2024 时间:2024年12月19-21日 地点:广州.中国进出口商品交易会展馆 承办单位:广州佛兴英耀展览服务有限公司 上海昶文展览服务有限公司…

基于springboot的蜗牛兼职网的设计与实现论文

摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景,运用软件工程原理和开发方法&#xff0c…

FISCO BCOS区块链平台上的智能合约压力测试指南

引言 在当今的分布式系统中,区块链技术因其去中心化、安全性和透明性而备受关注。随着区块链应用的不断扩展,对其性能和稳定性的要求也越来越高。因此,对区块链网络进行压力测试显得尤为重要。 目录 引言 1. 配置FISCO BCOS节点 2. 安装和…

strongswan编译报错:NID_sm2p256v1未定义

strongswan编译报错:NID_sm2p256v1未定义 现象: 原因: 我用的是openssl.-1.1.1d,发现NID_sm2p256v1曲线改为了NID_sm2(gmssl用的是NID_sm2p256v1)。对比了一下参数,是相同的。个人猜测是国际只…

C语言初学10:共同体

一、共同体作用 提供一种在相同内存位置存储不同数据类型的有效方式 二、共同体定义 union [union tag] //tag是可选参数 {member definition;member definition;...member definition; } [one or more union variables]; // 共同体变量是可选的 三、共同体占用空间大小 #…

Docker安装MySQL镜像实战分享

今天我们对Docker安装MySQL镜像进行实战分享,以更深入的了解容器的使用场景。我们在云付服务器Ubuntu环境上已经安装好了Docker,接下来我们开始安装mysql5.7版本,安装mysql有两种思路,直接拉取mysql镜像和自己做mysql镜像&#xf…

【leetcode C++】电话号码的字母组合

17. 电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 题目链接 . - 力扣(LeetCode&…

Linux学习-函数指针和指针函数

目录 字符串是char *型,代表的是字符串的第一个元素的地址 指针函数: 函数指针: 字符串是char *型,代表的是字符串的第一个元素的地址 指针函数: int *Fun(int a, int b); 是函数,函数的返回值类型是…

PaddleSeg分割框架解读[01] readme解读

简介 PaddleSeg是基于飞桨PaddlePaddle的端到端图像分割套件,内置45+模型算法及140+预训练模型,支持配置化驱动和API调用开发方式,打通数据标注、模型开发、训练、压缩、部署的全流程,提供语义分割、交互式分割、Matting、全景分割四大分割能力,助力算法在医疗、工业、遥…