关于 OceanBase 4.x 中被truncate的 table 不再支持进回收站的原因
近期,OceanBase的问答社区中收到了不少用户的询问,关于OceanBase 3.x版本支持被truncate的table进入回收站的功能,为何在升级到4.x版本后不再支持了?为了解答大家的疑惑,我们将通过这篇文章来浅析 OceanBase在4.x版本中为何会出现这一“功能回调”。
背景
尽管MySQL本身并不具备回收站这样的概念和功能,但对于DBA同学来说,误操作和误删数据却是常见的问题。若MySQL拥有类似回收站的功能,那么误删的数据就可以迅速且无损地被恢复。应广大蚂蚁 DBA 的强烈要求,OceanBase 在 MySQL 模式下也支持了类似于 Oracle 10g 中的回收站功能。
在 3.x 版本中,当 session 级别的系统变量 ob_enable_truncate_flashback 被置为 on 时,如果进行了一个 truncate table 的误操作,可以通过 flashback 还原执行 truncate table 之前的表和数据。
例如通过执行如下 SQL 序列,就可以把被 truncate 掉的 t1 中被 truncate 之前的数据还原到另外一张叫 truncated_t1 的表中。
show variables like 'recyclebin';set recyclebin = on; # 开启回收站的功能show variables like 'ob_enable_truncate_flashback';set ob_enable_truncate_flashback = on; # 开启 truncate table 进回收站的功能create table t1(c1 int);insert into t1 values(123);truncate table t1;show recyclebin;flashback table t1 to before drop rename to truncated_t1;
最近遇到很多用户和同学在问,3.x 版本支持被 truncate 的 table 进回收站,为什么 4.x 版本不支持了?
# 下面这个系统变量在 4.x 版本已经被废弃掉了(不生效了),官网文档有误。
> set ob_enable_truncate_flashback = on;> truncate table t1;> show recyclebin;
Empty set (0.010 sec)> flashback table t1 to before drop rename to truncated_t1;
ERROR 5270 (HY000): object not in RECYCLE BIN
原因分析
原因要从 OceanBase 回收站的实现方式,以及 3.x 以及 4.x 版本 truncate table 的实现方式说起。
回收站的实现方式
回收站的实现本质上是一种逻辑删除(或者叫标记删除),即把被删除的对象用内部标识进行记录,有该标识的对象对用户不可见。进入回收站的对象只修改了对象的元数据,底层数据没有任何改动。
对于回收站的实现,我们先从 show recyclebin 说起:show recyclebin 可以显示所有在回收站中对象信息,这些对象信息都保存在 __all_recyclebin 这张内部表中,每次将对象放入到回收站时,都会在该表中插入一条记录,FLASHBACK(还原) 或者 PURGE(清空)时会将信息从 __all_recyclebin 表中删除。
obclient [test]> show recyclebin;
+--------------------------------+------------------+----------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+------------------+----------+----------------------------+
| __recycle_$_1_1694438429313272 | liboyang_db | DATABASE | 2023-09-11 21:20:29.314951 |
| __recycle_$_1_1694438481392392 | __idx_504469_idx | INDEX | 2023-09-11 21:21:21.392822 |
| __recycle_$_1_1694438481414600 | t1 | TABLE | 2023-09-11 21:21:21.415038 |
+--------------------------------+------------------+----------+----------------------------+
3 rows in set (0.011 sec)obclient [test]> select object_name, original_name, type, gmt_create, database_id, table_id from oceanbase.__all_recyclebin;
+--------------------------------+------------------+------+----------------------------+-------------+----------+
| object_name | original_name | type | gmt_create | database_id | table_id |
+--------------------------------+------------------+------+----------------------------+-------------+----------+
| __recycle_$_1_1694438429313272 | liboyang_db | 4 | 2023-09-11 21:20:29.314951 | 500006 | -1 |
| __recycle_$_1_1694438481392392 | __idx_504469_idx | 2 | 2023-09-11 21:21:21.392822 | 500001 | 504470 |
| __recycle_$_1_1694438481414600 | t1 | 1 | 2023-09-11 21:21:21.415038 | 500001 | 504469 |
+--------------------------------+------------------+------+----------------------------+-------------+----------+
3 rows in set (0.002 sec)obclient [test]> purge database __recycle_$_1_1694438429313272;
Query OK, 0 rows affected (0.080 sec)obclient [test]> show recyclebin;
+--------------------------------+------------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+------------------+-------+----------------------------+
| __recycle_$_1_1694438481392392 | __idx_504469_idx | INDEX | 2023-09-11 21:21:21.392822 |
| __recycle_$_1_1694438481414600 | t1 | TABLE | 2023-09-11 21:21:21.415038 |
+--------------------------------+------------------+-------+----------------------------+
2 rows in set (0.011 sec)obclient [test]> flashback table t1 to before drop rename to dropped_t1;
Query OK, 0 rows affected (0.145 sec)obclient [test]> show recyclebin;
Empty set (0.010 sec)
为了支持 drop table 进入回收站的功能,OceanBase 为每个租户都增加了一个名为 __recyclebin 的默认库,对应的 database_id 都是 201004。
obclient [test]>
select database_id
from oceanbase.__all_database
where database_name = '__recyclebin';
+-------------+
| database_id |
+-------------+
| 201004 |
+-------------+
1 row in set (0.008 sec)
drop table 进回收站时,会修改被 drop 表的元数据信息 database_id 和 table_name,相当于把表从原来的库中移除,然后放入到这个 __recyclebin 库中。需要注意的是,drop table 时也会将表上的索引一起放到回收站里。
obclient [test]> create table t1(c1 int, index idx(c1));obclient [test]> drop table t1;obclient [test]> flashback table t1 to before drop rename to dropped_t1;obclient [test]>
select a.schema_version, a.table_id, a.database_id, a.table_name, b.ddl_stmt_str
from oceanbase.__all_table_history a, oceanbase.__all_ddl_operation b
where a.table_id = 504469 and a.table_id = b.table_id and a.schema_version = b.schema_version;
+------------------+----------+-------------+--------------------------------+--------------------------------------------------------+
| schema_version | table_id | database_id | table_name | ddl_stmt_str |
+------------------+----------+-------------+--------------------------------+--------------------------------------------------------+
| 1694438476085056 | 504469 | 500001 | t1 | create table t1(c1 int, index idx(c1)) |
| 1694438476174856 | 504469 | 500001 | t1 | |
| 1694438481405672 | 504469 | 500001 | t1 | |
| 1694438481414600 | 504469 | 201004 | __recycle_$_1_1694438481414600 | DROP TABLE `test`.`t1` |
| 1694438664151120 | 504469 | 201004 | __recycle_$_1_1694438481414600 | |
| 1694438664161728 | 504469 | 500001 | dropped_t1 | flashback table t1 to before drop rename to dropped_t1 |
+------------------+----------+-------------+--------------------------------+--------------------------------------------------------+
6 rows in set (0.014 sec)
所以删除一张表进回收站整个流程如下:
-
-
- 修改 table 的 database_id 和 table_name,库名为 __recyclebin,表名为 __recycle 开头的特定格式。
- 将表放入到回收站,即在 __all_recyclebin 表中增加相应的记录。
- 对于表上的各个索引表,也执行上述步骤。
-
flashback to before drop 是还原操作,相当于 drop to recyclebin 的逆运算,实现上和上述 drop to recyclebin 也都是正好相反的,这里不再赘述。
purge 是清空回收站,实现是先从 __recyclebin 删除这个对象的信息,然后再从 __all_table 和 __all_table_history 中把这个对象真正删除,这里不再赘述。
回收站中的其他对象,例如 tenant、database 等,实现上也都是类似的,这里不再赘述。
truncate table 的实现方式
3.x 版本的 truncate table
3.x 版本的 truncate table 实现上是转换成了 drop table + create table。例如执行一条 DDL truncate table t1,内部会在同一个事务中执行 drop table t1 和 create table t1。
因为 3.x 版本的 truncate table 有 drop table 这个步骤,并且 drop table 可以进回收站,所以 3.x 版本被 truncate table 之前的表和数据会跟随 drop table 这个动作进入回收站。这也就是在 3.x 版本如果我们进行了一个 truncate table 的误操作,为什么可以通过 flashback 还原执行 truncate table 之前的表和数据的原因了。
4.x 版本的 truncate table
OceanBase 在 4.x 版本新增加了一个 tablet 的概念,这是一个用户不感知的物理存储层的概念,表示可以迁移的数据块。基于这个 tablet,4.x 的 truncate table 实现上只需要修改分区对应的 tablet,不再复用 3.x 版本的 drop table + create table 的流程。即在 4.x 版本的 truncate table 中,实现变成了删除旧 tablet + 创建新 tablet,当 table 上的附属对象(例如 column、constraint、foreign key、partition、index 等)较多时,truncate table 性能可以得到巨大的优化。
因为 4.x 版本的 truncate table 已经没有 drop table 这个步骤了,所以也就不会再像 3.x 一样,把 truncate 过程中 drop 掉的这个 table 给放进回收站了。4.x 上 truncate table 前后 table 的元数据不会发生变更,只需要修改一下和存储相关的 tablet 即可。
4.x 版本为什么要调整 truncate table 的实现方式?
在 OceanBase 还是 3.x 版本时,部分客户会在业务逻辑中大量使用 truncate table 语句,但是大家都发现 OB 中 truncate table 的性能低于 Oracle。性能的消耗来自于两部分,系统表数据的更新和分区实体的创建。后者在 OB 3.x 版本上是需要创建 paxos 成员组的,步骤较多,但是在 OB 4.x 的单日志流架构下,新建分区只是在日志流内数据的操作,性能会大幅提升。而性能消耗的另外一部分是系统表数据的更新,要消除这一部分的开销,就需要改变 truncate table 的实现方式。
之前接触过一个使用 OceanBase 3.x 版本的用户,他们有上万张表,每张表都有几百个 column 和几百个 check 约束,所以每张表在 __all_column 和 __all_constraint 系统表中都会记录上百行数据。3.x 版本每次 truncate table 操作都要在 drop table 时对这些元信息执行删除操作,在 create table 时再对这些元信息执行写入操作,当 table 上的附属对象较多时,大量附属对象元信息的删除和写入会让 truncate table 耗费大量的时间。
而 OceanBase 4.x 中 truncate table 的实现不再修改表的元数据信息,所以 __all_column、__all_constraint 等系统表的数据都不会发生改变。数据的清除通过更换 tablet 来实现。__all_table 表内会增加一列 tablet_id 表示一张表对应的 tablet,truncate table 时创建一个新的空 tablet,将新 tablet_id 写入 __all_table 表替换之前的旧值,这样就完成了 truncate 表的操作,之后旧的 tablet 即可删除。对于分区表,会在 __all_part 表中记录每个分区对应的 tablet_id,truncate table 时将每个分区对应的 tablet 替换成新的空 tablet 即可。
熟悉 Oracle 的同学可以把 table_id 对应成 Oracle 的 object_id,把 tablet_id 对应成 Oracle 的data_object_id,上述 OceanBase 4.x 版本 truncate table 的实现方式就和 Oracle 的实现逻辑是类似的了。
其他
最后再说几个回收站功能中,我个人觉得比较有意思,且大家平时不容易关注到的点。
通过 original_name 来 flashback table
OceanBase 官网目前(2023.09.12)说:通过 flashback 还原回收站里的 table 时,只支持指定要恢复的数据库对象在回收站中的名称 object_name,不支持直接指定其被删除前的名称 original_name。
其实 OceanBase 也支持指定其被删除前的名称 original_name,如果回收站中的 table 有多个同名的 original_name,flashback 会还原最晚进回收站的那张表,所以 flashback original_name 的操作可以理解成是一个栈,后进先还原。该行为和 Oracle 的回收站一致。
接下来举个例子:
# 创建名字为 t1 的表,然后删除进回收站,重复三遍
obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.150 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.448 sec)obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.150 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.448 sec)obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.150 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.448 sec)# 回收站中会出现三张 original_name 为 t1 的表
obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694489277444056 | t1 | TABLE | 2023-09-12 11:27:57.450622 |
| __recycle_$_1_1694489280576008 | t1 | TABLE | 2023-09-12 11:28:00.577040 |
| __recycle_$_1_1694489499729088 | t1 | TABLE | 2023-09-12 11:31:39.729893 |
+--------------------------------+---------------+-------+----------------------------+
3 rows in set (0.011 sec)# 第一次 flashback 的 t1 是当前回收站中最晚(11:31)进回收站的那张 t1
obclient [test]> flashback table t1 to before drop rename to t1_1;
Query OK, 0 rows affected (0.123 sec)obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694489277444056 | t1 | TABLE | 2023-09-12 11:27:57.450622 |
| __recycle_$_1_1694489280576008 | t1 | TABLE | 2023-09-12 11:28:00.577040 |
+--------------------------------+---------------+-------+----------------------------+
2 rows in set (0.010 sec)# 第二次 flashback 的 t1 也是当前回收站中最晚(11:28)进回收站的那张 t1
obclient [test]> flashback table t1 to before drop rename to t1_2;
Query OK, 0 rows affected (0.089 sec)obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694489277444056 | t1 | TABLE | 2023-09-12 11:27:57.450622 |
+--------------------------------+---------------+-------+----------------------------+
1 row in set (0.012 sec)# 第三次直接通过 object_name 去 flashback 了
obclient [test]> flashback table __recycle_$_1_1694489277444056 to before drop rename to t1_3;
Query OK, 0 rows affected (0.093 sec)obclient [test]> show recyclebin;
Empty set (0.011 sec)
通过 original_name 来 purge table
OceanBase 官网目前说:通过 purge 清空回收站中的 table 时,只支持指定要删除的表在回收站中的名称 object_name,不支持直接指定表的名称 original_name。
其实 OceanBase 也支持指定其被删除前的名称 original_name,如果回收站中的 table 有多个同名的 original_name,purge 会清空最早进回收站的那张表,所以 purge original_name 的操作可以理解成是一个队列,先进先清空。该行为和 Oracle 的回收站一致。
接下来举个例子:
# 创建名字为 t1 的表,然后删除进回收站,重复三遍
obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.143 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.551 sec)obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.146 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.552 sec)obclient [test]> create table t1(c1 int);
Query OK, 0 rows affected (0.145 sec)obclient [test]> drop table t1;
Query OK, 0 rows affected (0.551 sec)# 回收站中会出现三张 original_name 为 t1 的表
obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694490316467736 | t1 | TABLE | 2023-09-12 11:45:16.468070 |
| __recycle_$_1_1694490326604712 | t1 | TABLE | 2023-09-12 11:45:26.605179 |
| __recycle_$_1_1694490329719016 | t1 | TABLE | 2023-09-12 11:45:29.719260 |
+--------------------------------+---------------+-------+----------------------------+
3 rows in set (0.017 sec)# 第一次 purge 的 t1 是当前回收站中最早(11:45:16)进回收站的那张 t1
obclient [test]> purge table t1;
Query OK, 0 rows affected (0.178 sec)obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694490326604712 | t1 | TABLE | 2023-09-12 11:45:26.605179 |
| __recycle_$_1_1694490329719016 | t1 | TABLE | 2023-09-12 11:45:29.719260 |
+--------------------------------+---------------+-------+----------------------------+
2 rows in set (0.011 sec)# 第二次 purge 的 t1 是当前回收站中最早(11:45:26)进回收站的那张 t1
obclient [test]> purge table t1;
Query OK, 0 rows affected (0.127 sec)obclient [test]> show recyclebin;
+--------------------------------+---------------+-------+----------------------------+
| OBJECT_NAME | ORIGINAL_NAME | TYPE | CREATETIME |
+--------------------------------+---------------+-------+----------------------------+
| __recycle_$_1_1694490329719016 | t1 | TABLE | 2023-09-12 11:45:29.719260 |
+--------------------------------+---------------+-------+----------------------------+
1 row in set (0.013 sec)# 第三次直接通过 object_name 去 purge 了
obclient [test]> purge table __recycle_$_1_1694490329719016;
Query OK, 0 rows affected (0.134 sec)obclient [test]> show recyclebin;
Empty set (0.010 sec)
这篇文章暂时就先写到这里了,如果大家对 OceanBase 的回收站还有什么问题,欢迎留言或者评论,我们一起学习和探讨~
更多内容
下面是往期的博客内容,欢迎感兴趣的同学相互交流学习:
《OceanBase 里的 schema 是什么》
《OceanBase 执行引擎的自适应技术》
《OceanBase 分布式下压技术》
相关文章:
关于 OceanBase 4.x 中被truncate的 table 不再支持进回收站的原因
近期,OceanBase的问答社区中收到了不少用户的询问,关于OceanBase 3.x版本支持被truncate的table进入回收站的功能,为何在升级到4.x版本后不再支持了?为了解答大家的疑惑,我们将通过这篇文章来浅析 OceanBase在4.x版本中…...
Numpy索引详解(数值索引,列表索引,布尔索引)
数值索引 数值索引类似列表索引操作使用[],参数为下标,[0,len-1),高维数组的索引使用多个[]连用分别代表一维索引,二维索引... import numpy as np import torchnp.random.seed(1) data1 np.arange(5) data2 np.arange(15).reshape(3,5) …...
大数据新视界 --大数据大厂之MongoDB与大数据:灵活文档数据库的应用场景
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
三年 Sparker 都不一定知道的算子内幕
一、如何在 mapPartitions 中释放资源 mapPartitions是一种对每个分区进行操作的转换操作,于常用的map操作类似,但它处理的是整个分区而不是单个元素。mapPartitions的应用场景适合处理需要在每个分区内批量处理数据的场景,通常用于优化性能…...
PG表空间
目录标题 PG表空间PostgreSQL表空间的最佳实践是什么?如何在PostgreSQL中创建和管理自定义表空间?PostgreSQL表空间对数据库性能的具体影响有哪些?在PostgreSQL中,如何迁移数据到不同的表空间以优化存储布局?PostgreSQ…...
谷粒商城のElasticsearch
文章目录 前言一、前置知识1、Elasticsearch 的结构2、倒排索引 (Inverted Index)2.1、 索引阶段2.2、查询阶段 二、环境准备1、安装Es2、安装Kibana3、安装 ik 分词器 三、项目整合1、引入依赖2、整合业务2.1、创建索引、文档、构建查询语句2.2、整合业务代码 后记 前言 本篇介…...
排队免单模式小程序开发
开发一个排队免单模式的小程序涉及多个方面,包括需求分析、界面设计、后端开发、数据库设计以及测试上线等。下面我将详细介绍每个步骤的概要: 1.需求分析 明确目标:首先确定小程序的核心功能,即排队免单模式的具体实现方式。例如…...
从OracleCloudWorld和财报看Oracle的转变
2024年9月9-12日Oracle Cloud World在美国拉斯维加斯盛大开幕 押注AI和云 Oracle 创始人Larry Ellison做了对Oracle战略和未来愿景的主旨演讲,在演讲中Larry将AI技术和云战略推到了前所未有的高度,从新的Oracle 23c改名到Oracle23ai,到Oracl…...
搭建 PHP
快速搭建 PHP 环境指南 PHP 是一种广泛用于 Web 开发的后端脚本语言,因其灵活性和易用性而受到开发者的青睐。无论是开发个人项目还是企业级应用,PHP 环境的搭建都是一个不可忽视的基础步骤。本指南将带您快速学习如何在不同平台上搭建 PHP 环境&#x…...
kubernetes技术详解,带你深入了解k8s
目录 一、Kubernetes简介 1.1 容器编排应用 1.2 Kubernetes简介 1.3 k8s的设计架构 1.3.1 k8s各个组件的用途 1.3.2 k8s各组件之间的调用关系 1.3.3 k8s的常用名词概念 1.3.4 k8s的分层结构 二、k8s集群环境搭建 2.1 k8s中容器的管理方式 2.2 k8s环境部署 2.2.1 禁用…...
Gateway学习笔记
目录 介绍: 核心概念 依赖 路由 断言 基本的断言工厂 自定义断言 过滤器 路由过滤器 过滤器工厂 自定义路由过滤器 全局过滤器 其他 过滤器执行顺序 前置后置(?) 跨域问题 yaml 解决 配置类解决 介绍&#x…...
创造增强叙事的互动:Allison Crank的沉浸式体验设计理念
在沉浸式技术日新月异的今天,如何通过用户交互增强叙事,而非分散注意力,成为了设计师们共同面临的挑战。作为用户体验设计师和研究员,Allison Crank以其独特的视角和丰富的经验,为我们揭示了这一领域的核心原则与实践方法。 叙事与互动的和谐共生 Allison Crank强调,互…...
Requests-HTML模块怎样安装和使用?
要安装和使用Requests-HTML模块,您可以按照以下步骤进行操作: 打开命令行界面(如Windows的命令提示符或Mac的终端)。 使用pip命令安装Requests-HTML模块。在命令行中输入以下命令并按回车键执行: pip install request…...
[网络]从零开始的计算机网络基础知识讲解
一、本次教程的目的 本次教程我只会带大叫了解网络的基础知识,了解网络请求的基本原理,为后面文章中可能会用到网络知识做铺垫。本次我们只会接触到网络相关的应用层,并不涉及协议的具体实现和数据转发的规则。也就是说,这篇教程是…...
wifiip地址可以随便改吗?wifi的ip地址怎么改变
对于普通用户来说,WiFi IP地址的管理和修改往往显得神秘而复杂。本文旨在深入探讨WiFi IP地址是否可以随意更改,以及如何正确地改变WiFi的IP地址。虎观代理小二将详细解释WiFi IP地址的基本概念、作用以及更改时需要注意的事项,帮助用户更好地…...
黑马十天精通MySQL知识点
一. MySQL概述 安装使用 MySQL安装完成之后,在系统启动时,会自动启动MySQL服务,无需手动启动。 也可以手动的通过指令启动停止,以管理员身份运行cmd,进入命令行执行如下指令: 1 、 net start mysql80…...
如何在 Vue 3 + Element Plus 项目中实现动态设置主题色以及深色模式切换
🔥 个人主页:空白诗 文章目录 一、引言二、项目依赖和环境配置1. VueUse2. use-element-plus-theme3. 安装依赖 三、实现深色模式切换1. 设置深色模式状态2. 模板中的深色模式切换按钮3. 深色模式的效果展示 四、动态切换主题色五、总结 一、引言 在现代…...
Android 如何实现搜索功能:本地搜索?数据模型如何设计?数据如何展示和保存?
目录 效果图为什么需要搜索功能如何设计搜索本地的功能,如何维护呢?总结 一、效果图 二、为什么需要搜索功能 找一个选项,需要花非常多的时间,并且每次都需要指导客户在哪里,现在只要让他们搜索一下就可以。这也是模…...
【K230 实战项目】气象时钟
【CanMV K230 AI视觉】 气象时钟 功能描述:说明HMDI资源3.5寸屏幕 使用方法 为了方便小伙伴们理解,请查看视频 B站连接 功能描述: 天气信息获取:通过连接到互联网,实时获取天气数据,包括温度、湿度、天气状…...
什么是 HTTP/3?下一代 Web 协议
毫无疑问,发展互联网底层的庞大协议基础设施是一项艰巨的任务。 HTTP 的下一个主要版本基于 QUIC 协议构建,并有望提供更好的性能和更高的安全性。 以下是 Web 应用程序开发人员需要了解的内容。 HTTP/3 的前景与风险 HTTP/3 致力于让互联网对每个人…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
