当前位置: 首页 > news >正文

数据库核心-redo、undo

一、redo日志

InnoDB操作以页为单位操作数据。并且首先操作内存中缓冲池的数据,然后刷新到disk中,但如果事务提交后宕机、未能刷新到disk中,就会造成不一致情况。
重做日志: 系统重启时按照修改步骤重新更新数据页

  • redo日志占用空间小
  • 顺序写入disk,不会随机IO

通用结构:

  • type:redo日志类型
  • space ID:表空间ID
  • page number:页号
  • data:具体内容

物理日志:记录的是内存操作,某个页面某个偏移量处修改了几个字节的值
根据修改字节数不同,又分为不同大小的日志。
但是,一个普通的insert语句,涉及的修改处不只是data的添加,还有页头信息的各种相关修改,杂七杂八,如果把这个修改点都记录下来,那这个物理redo日志是不是太多了,如果都写在一起,岂不是太冗余了,因此就有新的redo日志类型,针对不同行格式的数据产生不同的redo日志。这些日志既有物理页面意思,又有逻辑层面意思。只会把插入一条记录的必备要素记下来,之后重做时根据相关函数实现插入。

1.1Mini-Transaction

一个insert会涉及多个redo日志,但如果插入过程只记录了一部分redo日志,会导致重做结果不确定性,这是不能忍受的因此我们在执行具有原子性操作时,必须以组的形式记录日志。重做时,该组redo要么都恢复,要么都不做。
而Innodb中,有一个特殊类型的日志,该日志只有一个字段type。因此,需要保证原子性的一系列redo日志必须以该类型日志结尾。这样重做时,只要恢复到了该类型日志时,才认为完成了一个操作,不然,放弃之前恢复的其他结果。
**Mini-Transaction:**对底层页面进行一次原子访问的过程;一个MTR可以包含一组redo,用来记录某个原子操作。一条sql语句包含若干MTR;

1.2redo写入步骤

redo日志都被放在512字节的页中,类似于一个数据page,但这里称为block,同样有块头,存储基本信息,比如,块编号、已经使用多少字节等等。
同数据页,redoblock并不是直接写入disk,而是先写入bufferpool,(redo log buffer redo日志缓冲区),这片内存被划分为若干个连续的block。


写入buffer是顺序写入的,因此需要指明应该从buffer的哪个位置开始写——buf_free,该位置之后的就是空闲区;


一个事务由多个MTR组成,而一个MTR会产生多个日志,这些日志并不是产生就写入buffer,而是以MTR为单位,MTR结束时整个相关日志一起写入buffer,


刷盘时机:

  1. buffer空间不足:已经写入50%,就需要刷盘
  2. 事务提交:redo日志就是为了保持一致性,因此事务提交时,pagebuffer内容可能不会及时刷新,但redobuffer一定会及时刷新。
  3. 脏页刷新:因为特殊需求,pagebuffer中脏页刷新到disk,脏页对应的redo也需要提前刷新,并且因为redobuffer是顺序写入的,因此脏页日志前面的日志也会刷新
  4. 后台线程默认频率刷新redobuffer
  5. checkpoint刷新

磁盘中的redo日志由多个文件组成,成循环方式相连——日志文件组
日志文件组的前4个block2048字节记录管理信息,之后开始记录日志内容。


lsn-记录已经写入的redo日志量,这个值包括了head和tail,并且初始值就是8704,简单分析一下,系统刚启动,buffer刚刚初始化,lsn就要+12字节,因为虽然没日志,但第一个block的head要包括进去,然后随着工作,开始写日志,lsn不断增加,第一个block满了,就会使用第二个,lsn就要加个tail和head,不断重复下去。。。


bufferpool中会有一个flush链表,来记录被修改过的脏页信息,都是一个一个控制块,如果某个页第一次被修改,就会加入到flush链表的头部,如果之前修改过,那就修改对应控制块信息就行了;控制块中有两个信息oldest和newest,分别表示页面最早开始修改的lsn和最新修改的lsn。例如一个新的页被修改,对应的MTR在刚开始修改页时的lsn会记录在oldest中,之后修改完后,最新的lsn会记录在newest中。如果是之前修改过的页,那对应控制快的oldest不会变,只会修改newest


checkpoint: redo日志容量有限,随着bufferpool中的脏页被刷新到disk中,那么对应的redo日志占用的disk空间就没用了,就可以被重复利用。利用checkpoint_lsn表示当前系统中可以被覆盖的redo日志总量是多少。
步骤:

  1. 计算当前可以被覆盖的内存lsn最大是多少。flush链表尾部是最早修改的,该控制块的oldestlsn则表示最早的lsn,那么该lsn之前的就是可以被覆盖的!找到了可以被覆盖的lsn最大值。
  2. 将checkpoint_lsn与对应的redo日志文件组偏移量、checkpoint编号写到日志文件管理信息中。

崩溃恢复: 只需要恢复checkpoint_lsn之后的redo日志记录,虽有其中有的脏页可能已经刷新到disk中,但不确定是哪些,因为是异步进行的。
在redo日志组中第一个文件的管理信息中,两个block存储了checkpoint_lsn的信息,但我们需要最新的,而其中的checkpoint_no表示checkpoint次数,因此只需要对比两个该参数的值,大的表示记录的最新的信息,然后找到存储的checkpoint_lsn、redo日志文件组偏移量checkpoint_offset,这样起始位置就找到了,而终止位置,每个block头信息都有个对应存储量,没有存储满的就是最后一个,就找到中止位置了。

这样顺序遍历就可以恢复日志记录,但效率有点慢;
利用redo日志的spaceID和pageid计算哈希值,把两个属性相同的放在同一个槽中,因为这是操作同一个表的,放在一起效率更高,避免读取页面的随机IO,加快恢复速度。

刚才说某些脏页可能被刷新到disk中了,每个页头都一个变量表示最新修改的lsn,如果执行checkpoint,那么刷新的页中记录的改变量值就会大于整个redo日志组的checkpoint_lsn,所以处于[checkpoint_lsn,变量]之间的日志就不需要redo,而小于checkpoint_lsn的本身已经写到disk中了,因此只需要redo大于变量的那部分。

二、undo日志

redo保证了事务一致性,那么原子性呢,需要事务执行一半的操作撤销,也就是回滚——undo log

事务只有在进行增删改、创建临时表时才会分配事务id,只读事务没有事务id,默认为0

row_id,当表中没有定义主键并且没有不允许为NULL的unique键时,系统就会自动加row_id的隐藏列,而trx_id表示操作该记录的最新事务id,都很好理解了。

undo日志因为操作不同而分为不同的日志类型。

插入:
另一个隐藏列roll_point就是一个指针,指向了改记录对应的undo日志,也就表示改记录的上一个历史版本,MVCC会用到。


删除:
页面头信息会根据next_point组成一个正常记录的单向链表;同时page_free指向删除链表,表示空间可以重复利用的。而delete操作,首先会将记录删除标记位设置为1,此时仍处于正常链表中,是一个中间状态记录(delete mark)。当delete操作提交时,才会将记录移动到删除链表中的头结点处(purge)。值得注意的是,当插入记录时,首先判断删除链表头结点的空间是否可以存储新纪录,如果不可以,直接另开辟空间存储,不会遍历删除链表!如果可以,就重复利用该空间,当然,会有一小部分空间得不到利用,称为碎片空间,该部分会在整个页的删除节点都利用完了,此时才会使用,将整个链表重构,这样那些碎片空间就整理在一起了,可以被利用,但同时也会耗费性能。
而undo肯定是考虑事务未提交的情况下哎,也就只考虑delete mark阶段,


更新:
更新就情况很多了,涉及主键更新、不涉及的;更新前后大小一致的、不一致的。
如果更新前后大小一致,直接原地更新即可!如果大小不一致,会讲旧记录删掉,插入新纪录以实现更新效果;
如果不更新主键,会有一种新的undo日志类型来表示,记录各种信息。但如果更新主键,那就麻烦了,因为聚簇索引有排序,如果更新的值变化很大,索引中的位置就要变化,跨度多个页,因此首先是旧记录的deletemark,然后更新后记录的插入。事务提交之后deletemark才会执行purge,与之前的更新大小不一致做区分!


之前都是聚簇索引,如果说是二级索引,插入和删除操作差不多,但更新不一样会对二级索引b+树进行更改。


会有专门存储undo日志的page,大体结构与其他page一致,不过会有个undopageheader,这是特有的,里面记录了存储什么类型undo日志(大类,并不是前面介绍的很细致的undo类型:广义的插入和更新;因为插入undo事务提交后会删除,而更新的需要支持mvcc),写入终止位置偏移量,写入undo日志起始位置偏移量。这是从空间页的角度看undo日志的。
事务角度: 一个事务涉及多个语句,一个语句会产生多个undo日志,所以事务执行产生很多undo日志,一个page可能放不写,因此需要把同一个事务的undo日志连成链条。而之前说的undo页面有两大类分开存储,因此,一个事务有两条双向链表页面,而Innodb规定对于普通表和临时表的操作产生不同的undo日志,因此又变成了4个链表!并且并不是一次都分配空间的,而是随着事务执行,用到哪个就分配哪个,因此4个是上限,实际多少个根据事务操作而定。不同事务之间链表不同。


undolog写入过程:
首先回顾一下段的概念,逻辑上的内存划分方法,根据程序员自己需求进行划分,索引被划为为两个段-叶子节点段、非叶子节点段。逻辑上将离散的页面分成两部分。每个段有一个INODE Entry结构记录段信息,每个页面的id,段id、链表地址等等。而为了重定位这个结构,有一个Segment Header记录了哪个INODE的表空间、页号,偏移量。就能找到那个段了。


每一个undo页面链表对应一个段,链表中的节点空间都是从这个段中申请的,所以链表头节点有个undo log segment header结构,存储这个段的相关信息,一个段也叫一组。

重用undo页面:如果修改的记录很少,undo页面链表很占用空间,不值得,因此事务提交后会重用该事务的undo页面链表。能重用的页面满足两个要求:

  1. 页面链表只包含一个undo页面
  2. 页面已经使用的空间小于整个页面空间的3/4

而页面链表分为了insert和update两种,不同类型链表重用策略不一样
insert: 插入记录日志会在事务提交后就没用了,因此重用时直接覆盖原本的旧undo记录即可!
update: 这个undo日志在事务提交后不能被删除,需要支持MVCC,因此不能覆盖,在后面接着写就好。

回滚段: 我们知道一个事务执行时最多分配4个undo页面链表,为了统一管理,有一个Rollback Segment Header的页面,存储了该事务所有页面链表的first undo page页号,称为undo slot
,根据这个信息管理具体的页面链表
每个RSH都对应一个段,就是回滚段,这个段只有一个页面。

执行过程:

  1. 初始化时,没有undo日志,因此回滚段中的undo slot为null。
  2. 开始执行,需要undo日志,如果slot为null,那么就在表空间新创建一个段,用来记录页面链表,申请一个页面当做头页,更新undo slot;如果不是null,表示已经有一个页面链表了,需要跳到下一个undo slot,重复之前步骤

一个回滚段中有1024个undo slot,如果都不为null,说明都有分配了,那新事务就不能获得undo日志链表,就会报错。
当事务提交时,所有undoslot都会被处理:

  • 如果指向的页面链表可以被重用,就处于被缓存状态,两种类型链表对应两种类型的缓存链表,分别插入。
  • 如果不能被重用,再根据类型判断,如果是insert,那就释放掉;如果是update,放入history中,MVCC中的版本链!

之前说过一个回滚段只有1024个slot,显然太少了,因此随着更新,定义了128个回滚段,对应128个RSH页面,在系统表空间的第5号页面的某个区域内有128个8字节的格子,每个格子有两个属性,一个id,另一个是页号,页号就是回滚段的RSH页号,这就方便多了。这些回滚段也是有分类的,下面详细描述一下:
1. 1~32号回滚段属于一类,这些回滚段必须再临时表空间中。我们在写undo日志过程本身就是写数据,那也会产生redo日志。但对于临时表来说,修改临时表产生的undo日志只会在系统运行中有效,如果系统崩溃,重启时是不需要恢复对应页面的。因此针对临时表的undo日志,没有对应的redo日志!因此操作临时表的undo日志需要单独区分
2.0,33~127属于一类,0号回滚段必须在系统表空间中,其他的可以在系统表空间,也可以在自己配制的undo表空间中,同时写undo的过程伴随有redo日志。

MVCC中用到的回滚指针,指向就是一个undo日志,根据这个undo日志可以得到某一个版本的数据记录,构成了一个版本链。

事务执行过程中分配Undo页面链表的过程:

  1. 事务在执行过程中对普通表的记录首次做改动之前,首先会到系统表空间的第 5 号页面中分配一个回滚段(其实就是获取一个 Rollback Segment Header 页面的地址)。一旦某个回滚段被分配给了这个事务,那么之后该事务中再对普通表的记录做改动时,就不会重复分配了。使用传说中的 round-robin (循环使用)方式来分配回滚段。比如当前事务分配了第 0 号回滚段,那么下一个事务就要分配第 33 号回滚段,下下个事务就要分配第 34 号回滚段,简单一点的说就是这些回滚段被轮着分配给不同的事务(就是这么简单粗暴,没啥好说的)。
  2. 在分配到回滚段后,首先看一下这个回滚段的两个 cached链表 有没有已经缓存了的 undo slot ,比如如果事务做的是 INSERT 操作,就去回滚段对应的 insert undo cached链表 中看看有没有缓存的 undo slot ;如果事务做的是 DELETE 操作,就去回滚段对应的 update undo cached链表 中看看有没有缓存的 undoslot 。如果有缓存的 undo slot ,那么就把这个缓存的 undo slot 分配给该事务。如果没有缓存的 undo slot 可供分配,那么就要到 Rollback Segment Header 页面中找一个可用的 undoslot 分配给当前事务。
  3. 找到可用的 undo slot 后,如果该 undo slot 是从 cached链表 中获取的,那么它对应的 Undo Log Segment 已经分配了,否则的话需要重新分配一个 Undo Log Segment ,然后从该 Undo Log Segment 中申请 一个页面作为 Undo页面 链表的 first undo page 。
  4. 然后事务就可以把 undo日志 写入到上边申请的 Undo页面 链表了

最后一个问题,系统崩溃后未提交事务写的redo日志怎么办?
系统崩溃,有可能,一个未提交的事务写的redo日志已经刷盘到disk,这样系统重启后redo的话,岂不是把未提交事务做的一半更改还原了?显然违背了事务原子性,因此需要将这部分数据undo!所以需要找到那些未提交事务的id,进行undo操作。
系统重启后,首先在第5号页面的128回滚段中,看其中1024个undoslot哪些不为空,然后判断这些不为空的undo页面链表中第一个页面的undologsegmentheader的属性STATE中判断该undo页面链表是否处于活跃状态。处于活跃状态就表明,系统宕机前该事务还没有提交,就是我们需要undo的事务,根据该undo页面链表中记录的各种属性来找出对应undo日志,进行回滚!

相关文章:

数据库核心-redo、undo

一、redo日志 InnoDB操作以页为单位操作数据。并且首先操作内存中缓冲池的数据,然后刷新到disk中,但如果事务提交后宕机、未能刷新到disk中,就会造成不一致情况。 重做日志: 系统重启时按照修改步骤重新更新数据页 redo日志占用…...

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_core_module

定义在 src\core\nginx.c ngx_module_t ngx_core_module {NGX_MODULE_V1,&ngx_core_module_ctx, /* module context */ngx_core_commands, /* module directives */NGX_CORE_MODULE, /* module type */NULL…...

SQLAlchemy系列教程:如何执行原生SQL

Python中的数据库交互提供了高级API。但是,有时您可能需要执行原始SQL以提高效率或利用数据库特定的特性。本指南介绍在SQLAlchemy框架内执行原始SQL。 在SQLAlchemy中执行原生SQL SQLAlchemy虽然以其对象-关系映射(ORM)功能而闻名&#xff…...

怎么实现: 大语言模型微调案例

怎么实现: 大语言模型微调案例 目录 怎么实现: 大语言模型微调案例输入一个反常识的问题:首都在北京天安门之后对输出模型进行测试:首都在北京天安门微调代码:测试微调模型代码:微调输出模型结构输出模型参数大小对比Qwen 2.5_0.5:53MB输出模型:951MB 是一样的,没有进行…...

【Linux内核系列】:深入理解缓冲区

🔥 本文专栏:Linux 🌸作者主页:努力努力再努力wz ★★★ 本文前置知识: 文件系统以及相关系统调用接口 输入以及输出重定向 那么在此前的学习中,我们了解了文件的概念以及相关的系统调用接口,并…...

【Qt】成员函数指针

一、成员函数指针的本质 与普通函数指针的区别: // 普通函数指针 void (*funcPtr)() &普通函数;// 成员函数指针 void (MyClass::*memberFuncPtr)() &MyClass::成员函数;• 绑定对象:成员函数指针必须与类的实例对象结合使用 • 隐含 this 指…...

关于 Can Utils 的详细介绍、使用方法及配置指南

Can Utils:开源CAN总线工具集合 一、Can Utils简介 Can Utils 是一组开源的CAN总线工具链,专为嵌入式开发者和网络诊断工程师设计,支持Linux、Windows和macOS系统。它包含一系列轻量级命令行工具(如 cantoolz、candump、canbus …...

【Academy】OAuth 2.0 身份验证漏洞 ------ OAuth 2.0 authentication vulnerabilities

OAuth 2.0 身份验证漏洞 ------ OAuth 2.0 authentication vulnerabilities 1. 什么是 OAuth?2. OAuth 2.0 是如何工作的?3. OAuth 授权类型3.1 OAuth 范围3.2 授权代码授权类型3.3 隐式授权类型 4. OAuth 身份验证4.1 识别 OAuth 身份验证4.2 侦察OAuth…...

dify中使用NL2SQL

在 Dify 工作流中融入 NL2SQL(自然语言转 SQL)之能力,可依循如下步骤达成,借由 Dify 的模块化设计以及模型编排之功能,优化数据库查询之智能化交互: 一、环境准备与 Dify 部署 安装 Docker 与 Dify 务须确…...

android viewmodel如何使用

嗯,我现在要学习如何在Android中使用ViewModel。我之前听说过ViewModel是用来管理UI相关数据的,这样在配置变化比如屏幕旋转时数据不会丢失。但具体怎么用呢?我需要先回忆一下相关的知识。 首先,ViewModel应该是Android Architec…...

蓝桥杯备赛-基础训练(四)字符串 day17

好久不见,今天开始继续更新,或许拿不了奖,但是希望记录自己学习的过程,如果感觉有收获的同学在下面多多评论说说我代码的缺陷,感谢大家! 1、反转字符串 编写一个函数,其作用是将输入的字符串反…...

AI Agent开发框架分析:前端视角

1. Mastra (https://mastra.ai/docs) 优点: 提供直观的界面构建器,适合无代码/低代码开发支持JavaScript/TypeScript,可直接集成到前端项目可视化工作流设计,降低入门门槛内置多种UI组件,加速前端开发 缺点&#xf…...

第3节:IP地址分类与子网划分实战指南

IP地址分类与子网划分实战指南:从小白到入门 在网络通信中,IP地址是设备之间相互识别和通信的基础。无论是家庭网络还是企业网络,IP地址的分配和管理都是网络运维的核心任务之一。然而,对于初学者来说,IP地址的分类、子网掩码、CIDR(无类别域间路由)和VLSM(可变长子网…...

贪心算法三

> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是贪心算法,并且掌握贪心算法。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! >…...

pytest基础知识

pytest知识了解 pytest的基础知识了解:Python测试框架之pytest详解_lovedingd的博客-CSDN博客_pytest框架 (包含设置断点,pdb,获取最慢的10个用例的执行耗时) pytest-pytest.main()运行测试用例,pytest参数: pytest-…...

JavaWeb后端基础(7)AOP

AOP是Spring框架的核心之一,那什么是AOP?AOP:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。AOP是一种思想,而在Spring框…...

[AI]从零开始的ComflyUI安装教程

一、前言 AI画图如今已经进化到了让人难以想象的地步。早在2022年各大视频网站上就出现了许多真人使用AI绘制二次元形象的视频。在那个时期,也有人凭借AI画图狠狠的吃到了一波AI红利。在现在,对于普通人来说,AI画图仍然是非常值得探索的。不管…...

文本对抗样本系列的论文阅读笔记(整理合订)

文本对抗样本系列的论文阅读笔记 以前调研文本对抗样本时的论文笔记梳理,论文都很经典,有现成的框架(TextAttack)可以直接用,论文中部分内容直接是截取自论文,所以存在中英混合笔记的情况。 BERT-Attack …...

鸿基智启:东土科技为具身智能时代构建确定性底座

人类文明的每一次跨越都伴随着工具的革新。从蒸汽机的齿轮到计算机的代码,生产力的进化始终与技术的“具身化”紧密相连。当大语言模型掀起认知革命,具身智能正以“物理实体自主决策”的双重属性重新定义工业、医疗、服务等领域的运行逻辑。在这场革命中…...

javascript-es6 (六)

编程思想 面向过程 面向过程 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次 调用就可以了 就是按照我们分析好了的步骤,按照步骤解决问题 面向对象 面向对象 是把事务分解成为一个个对象&am…...

【leetcode hot 100 19】删除链表的第N个节点

解法一:将ListNode放入ArrayList中,要删除的元素为num list.size()-n。如果num 0则将头节点删除;否则利用num-1个元素的next删除第num个元素。 /*** Definition for singly-linked list.* public class ListNode {* int val;* Lis…...

微信小程序将markdown内容转为pdf并下载

要在微信小程序中将Markdown内容转换为PDF并下载,您可以使用以下方法: 方法一:使用第三方API服务 选择第三方API服务: 可以选择像 Pandoc、Markdown-PDF 或 PDFShift 这样的服务,将Markdown转换为PDF。例如,PDFShift 提供了一个API接口,可以将Markdown内容转换为PDF格式…...

【贪心算法】将数组和减半的最小操作数

1.题目解析 2208. 将数组和减半的最少操作次数 - 力扣(LeetCode) 2.讲解算法原理 使用当前数组中最大的数将它减半,,直到数组和减小到一半为止,从而快速达到目的 重点是找到最大数,可以采用大根堆快速达到…...

【面试】Kafka

Kafka 1、为什么要使用 kafka2、Kafka 的架构是怎么样的3、什么是 Kafka 的重平衡机制4、Kafka 几种选举过程5、Kafka 高水位了解过吗6、Kafka 如何保证消息不丢失7、Kafka 如何保证消息不重复消费8、Kafka 为什么这么快 1、为什么要使用 kafka 1. 解耦:在一个复杂…...

PHP MySQL 创建数据库

PHP MySQL 创建数据库 引言 在网站开发中,数据库是存储和管理数据的核心部分。PHP 和 MySQL 是最常用的网页开发语言和数据库管理系统之一。本文将详细介绍如何在 PHP 中使用 MySQL 创建数据库,并对其操作进行详细讲解。 前提条件 在开始创建数据库之…...

通义万相 2.1 × 蓝耘智算:AIGC 界的「黄金搭档」如何重塑创作未来?

我的个人主页 我的专栏: 人工智能领域、java-数据结构、Javase、C语言,希望能帮助到大家!!! 点赞👍收藏❤ 引言 在当今数字化浪潮席卷的时代,AIGC(生成式人工智能)领域正…...

【面试题系列】:使用消息队列怎么防止消息重复?从原理到实战……

一、消息队列的核心价值与挑战 消息队列(MQ)作为现代分布式系统的基础设施,其核心价值在于解耦、削峰填谷和异步通信。但在追求高可靠性的过程中,消息重复成为必须攻克的技术难题。根据调研数据,在生产环境中消息重复…...

Damage与Injury

### “Damage”和“Injury”的区别 “Damage”和“Injury”都有“损害”或“伤害”的意思,但它们的用法、语境和侧重点有所不同。以下是从词性、适用对象、语义侧重和具体场景四个方面详细对比两者的区别: --- #### 1. **词性** - **Damage**&#xf…...

18 HarmonyOS NEXT UVList组件开发指南(五)

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! 第五篇:UVList组件最佳实践与实际应用案例 文章目录 第五篇:UVList组件最佳实践与实际应用案例1. 最佳实践总结1.1 组件设计…...

vue3组合式API怎么获取全局变量globalProperties

设置全局变量 main.ts app.config.globalProperties.$category { index: 0 } 获取全局变量 const { appContext } getCurrentInstance() as ComponentInternalInstance console.log(appContext.config.globalProperties.$category) 或是 const { proxy } getCurrentInstance…...

华为机试牛客刷题之HJ14 字符串排序

HJ14 字符串排序 描述 对于给定的由大小写字母混合构成的 n 个单词&#xff0c;输出按字典序从小到大排序后的结果。 从字符串的第一个字符开始逐个比较&#xff0c;直到找到第一个不同的位置&#xff0c;通过比较这个位置字符对应的&#xff08;A<⋯<Z<a<⋯<…...

CPU 负载 和 CPU利用率 的区别

简单记录下 top 命令中&#xff0c;CPU利用率核CPU负载的概念&#xff0c; &#xff08;1&#xff09;CPU利用率&#xff1a;指在一段时间内 表示 CPU 实际工作时间占总时间的百分比。表示正在执行进程的时间比例&#xff0c;包括用户空间和内核空间程序的执行时间。通常包含以…...

SSM框架

SSM 框架是 Java Web 开发中广泛使用的经典组合&#xff0c;由 Spring、Spring MVC 和 MyBatis 三个开源框架整合而成&#xff0c;适用于构建中大型企业级应用。 1. SSM框架组成 框架作用核心特性Spring管理业务层&#xff08;Service&#xff09;和持久层&#xff08;DAO&am…...

maven无法解析插件 org.apache.maven.plugins:maven-jar-plugin:3.4.1

解决流程 1.修改maven仓库库地址 2.删除本地的maven仓库 maven插件一直加载有问题: 无法解析插件 org.apache.maven.plugins:maven-jar-plugin:3.4.1 开始以为maven版本有问题&#xff0c;重装了maven&#xff0c;重装了idea工具。结果问题还是没解决。研究之后发现&#xf…...

如何修复“RPC 服务器不可用”错误

远程过程调用&#xff08;Remote Procedure Call&#xff0c; RPC&#xff09;是允许客户端在不同计算机上执行进程的众多可用网络进程之一。本文将深入探讨RPC如何在不同的软件系统之间实现无缝消息交换&#xff0c;同时重点介绍与RPC相关的常见错误的一些原因。 什么是远程过…...

晋升系列4:学习方法

每一个成功的人&#xff0c;都是从底层开始打怪&#xff0c;不断的总结经验&#xff0c;一步一步打上来的。在这个过程中需要坚持、总结方法论。 对一件事情长久坚持的人其实比较少&#xff0c;在坚持的人中&#xff0c;不断的总结优化的更少&#xff0c;所以最终达到高级别的…...

单链表-代码精简版

单链表核心知识详解 单链表是一种动态存储的线性数据结构&#xff0c;其特点是逻辑上连续&#xff0c;物理上非连续&#xff0c;每个节点包含数据域和指向下一个节点的指针域。以下是核心知识点与完整实现代码&#xff1a; 一、单链表的结构定义 单链表节点通过结构体自引用…...

关于前后端整合和打包成exe文件的个人的总结和思考

前言 感觉有很多东西&#xff0c;不知道写什么&#xff0c;随便写点吧。 正文 前后端合并 就不说怎么开发的&#xff0c;就说点个人感觉重要的东西。 前端用ReactViteaxios随便写一个demo&#xff0c;用于CRUD。 后端用Django REST Framework。 设置前端打包 import { …...

基于muduo+mysql+jsoncpp的简易HTTPWebServer

一、项目介绍 本项目基于C语言、陈硕老师的muduo网络库、mysql数据库以及jsoncpp&#xff0c;服务器监听两个端口&#xff0c;一个端口用于处理http请求&#xff0c;另一个端口用于处理发送来的json数据。 此项目在实现时&#xff0c;识别出车牌后打包为json数据发送给后端服务…...

Java/Kotlin逆向基础与Smali语法精解

1. 法律警示与道德边界 1.1 司法判例深度剖析 案例一&#xff1a;2021年某游戏外挂团伙刑事案 犯罪手法&#xff1a;逆向《王者荣耀》通信协议&#xff0c;修改战斗数据包 技术细节&#xff1a;Hook libil2cpp.so的SendPacket函数 量刑依据&#xff1a;非法经营罪&#xff…...

C++:入门详解(关于C与C++基本差别)

目录 一.C的第一个程序 二.命名空间&#xff08;namespace&#xff09; 1.命名空间的定义与使用&#xff1a; &#xff08;1&#xff09;命名空间里可以定义变量&#xff0c;函数&#xff0c;结构体等多种类型 &#xff08;2&#xff09;命名空间调用&#xff08;&#xf…...

CI/CD—GitLab钩子触发Jenkins自动构建项目

GitLab钩子简介&#xff1a; 项目钩子 项目钩子是针对单个项目的钩子&#xff0c;会在项目级别的特定事件发生时触发。这些事件包括代码推送、合并请求创建、问题创建等。项目钩子由项目管理员或具有相应权限的用户进行配置&#xff0c;仅对特定项目生效。 使用场景&#xff1a…...

RPA 职业前景:个人职场发展的 “新机遇”

1. RPA职业定义与范畴 1.1 RPA核心概念 机器人流程自动化&#xff08;RPA&#xff09;是一种通过软件机器人模拟人类操作&#xff0c;自动执行重复性、规则性任务的技术。RPA的核心在于其能够高效、准确地处理大量数据和流程&#xff0c;减少人工干预&#xff0c;从而提高工作…...

【CSS3】金丹篇

目录 标准流概念元素类型及排列规则块级元素行内元素行内块元素 标准流的特点打破标准流 浮动基本使用清除浮动额外标签法单伪元素法双伪元素法&#xff08;推荐&#xff09;overflow 法 Flex 布局Flex 组成主轴对齐方式侧轴对齐方式修改主轴方向弹性盒子伸缩比弹性盒子换行行对…...

Git(一)

一、介绍 二、Git代码托管服务 三、Git常用命令 全局设置&#xff1a; 获取Git仓库&#xff1a; 工作区、暂存区、版本库概念&#xff1a; Git工作区文件的状态&#xff1a; 本地仓库操作&#xff1a; 远程仓库操作&#xff1a; 分支操作&#xff1a; 标签操作&#xff1a; 四…...

Python大数据可视化:基于spark的短视频推荐系统的设计与实现_django+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 热门视频界面 用户界面 用户反馈界面 论坛交流界面 系统…...

面试题之react useMemo和uesCallback

在面试中&#xff0c;关于 React 中的 useMemo 和 useCallback 的区别 是一个常见的问题。 useMemo 和 useCallback 的区别 1. 功能定义 useMemo&#xff1a; 用于缓存计算结果&#xff0c;避免在每次组件渲染时重新计算复杂的值。它接受一个计算函数和一个依赖数组&#xff0…...

K8S学习之基础十九:k8s的四层代理Service

K8S四层代理Service 四层负载均衡Service 在k8s中&#xff0c;访问pod可以通过ip端口的方式&#xff0c;但是pod是由生命 周期的&#xff0c;pod在重启的时候ip地址往往会发生变化&#xff0c;访问pod就需要新的ip地址&#xff0c;这样就会很麻烦&#xff0c;每次pod地址改变就…...

C++:string容器(下篇)

1.string浅拷贝的问题 // 为了和标准库区分&#xff0c;此处使用String class String { public :/*String():_str(new char[1]){*_str \0;}*///String(const char* str "\0") // 错误示范//String(const char* str nullptr) // 错误示范String(const char* str …...

sudo systemctl restart docker 重启docker失败

一般会使用如下命令&#xff0c;进行docker重启。 sudo systemctl daemon-reload sudo systemctl restart docker 重启失败时&#xff0c;会提示&#xff1a;Job for docker.service failed because the control process exited with error code. See "systemctl status…...