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

MySQL的底层原理与架构

前言

了解MySQL的架构和原理对于很多的后续很多的操作会有很大的帮助与理解。并且很多知识都与底层架构相关联。

了解MySQL架构

通过上面的架构图可以得知,Server层中主要由 连接器、查询缓存、解析器/分析器、优化器、执行器 几部分组成的,下面将主要描述下这几部分。

1、连接器:

客户端想要对数据库进行操作时,前提是与数据库建立好连接;而连接器就是用来负责跟客户端建立连接、获取权限、维持和管理连接的。

(1)连接方式:

MySQL既支持短连接,也支持长连接。短连接就是操作完毕后,马上close关掉。长连接可以保持打开,减少服务端创建和释放连接的消耗,后续程序访问的时候还可以使用这个连接。

(2)连接池:

与客户端的连接池一样,为了减少频繁创建和销毁连接造成的不必要的性能损失,这里也采用了“池化”的思想,通过数据库连接池去管理连接。一般我们会在连接池中使用长连接,例如:druid、c3p0、dbcp等

2、查询缓存:

MySQL缓存是默认关闭的,也就是说不推荐使用缓存,并且在 MySQL 8.0 版本直接将查询缓存的整块功能删掉了。因为缓存中的格式是kye(sql),value(数据)的方式保存的,如果SQL只要有一点不同那么就不会走缓存。其次是表中的数据很多时候都是会变化的,而数据变化了那么缓存也就没有意义。

3、分析/解析器:

分析器的工作主要是对要执行的SQL语句进行解析,最终得到抽象语法树,然后再使用预处理器判断抽象语法树中的表是否存在,如果存在的话,在接着判断select投影列字段是否在表中存在等。

(1)词法分析:

词法分析用于将SQL拆解为不可再分的原子符号,称为Token。并根据不同数据库方言所提供的字典,将其归类为关键字,表达式,字面量和操作符。

(2)语法分析:

语法分析就是根据词法分析拆解出来的Token(原子符号)将SQL语句转换为抽象语法树。

(3)预处理器:

预处理是用来对生成的 抽象语法树 进行语义校验,语义校验就是对查询的表、select投影列字段进行校验,判断表、字段是否存在等;

SELECT id, name FROM t_user WHERE status = ‘ACTIVE’ AND age > 18

以上述SQL为例,经过词法分析与语法分析后会得到的抽象语法树如下图。

4、优化器:

优化器的作用主要是将SQL经过词法解析/语法解析后得到的语法树,通过MySQL的数据字典和统计信息的内容,经过一系列运算 ,最终得出一个执行计划,包括选择使用哪个索引。

在优化过程中,经过的一系列运算是什么呢?

(1)逻辑变换:例如SQL的where条件中存在 8>9,那逻辑转换就是将语法树中存在的这种常量表达式直接进行化简,化简为 false;除了化简还有常量表达式计算等。

(2)代价优化:就是通过付出一些数据统计分析的代价,来得到这个SQL执行是否可以走索引,以及走哪些索引;除此之外,在多表关联查询中,确定最终表join的顺序等

在分析是否走索引查询时,是通过进行动态数据采样统计分析出来;只要是统计分析出来的,那就可能会存在分析错误的情况,所以在SQL执行不走索引时,也要考虑到这方面的因素

5、执行器:

MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。执行器最终就是根据一系列的执行计划去调用存储引擎提供的API接口去调用操作数据,完成SQL的执行

开始执行的时候,要先判断一下建立连接的对象对这个表有没有执行操作的权限,如果没有,就会返回没有权限的错误;如果有,就按照生成的执行计划进行执行。

InnoDB存储引擎:

存储引擎是对底层物理数据执行实际操作的组件,为Server服务器层提供各种操作数据的 API,数据是被存放在内存或者是磁盘中的。MySQL 支持插件式的存储引擎,包括 InnoDB 、MyISAM、Memory 等。一般情况下,MySQL默认使用的存储引擎是 InnoDB。如下图所示,InnoDB存储引擎整体分为内存架构(Memory Structures)和磁盘架构(Disk Structures)

1、Buffer Pool:

Buffer Pool (缓冲池)是 InnoDB 存储引擎中非常重要的内存结构,类似 Redis 一样的作用,起到一个缓存的作用。MySQL 的数据最终是存储在磁盘中的,如果没有 Buffer Pool,那么每次的数据库请求都会磁盘中查找,这样必然会存在 IO 操作。但是有了 Buffer Pool,在第一次查询时就会将查询的结果保存到 Buffer Pool 中,这样后面再有请求时就会先从缓冲池中去查询如果没有再去磁盘中查找,然后在放到 Buffer Pool 中,如下图:

UPDATE students SET stuName = ‘小强’ WHERE id = 1

以上述SQL为例,那么它的执行顺序大致如下

  • (1)innodb 存储引擎先在缓冲池中查找 id=1 的这条数据是否存在
  • (2)如果缓存不存在,那么就去磁盘中加载,并将其存放在缓冲池中
  • (3)该条记录会被加上一个独占锁

**??**buffer pool 和 前面提到的查询缓存的区别:

(1)查询缓存:查询缓存位于Server层,MySQL Server首选会从查询缓存中查看是否曾经执行过这个SQL,如果曾经执行过的话,之前执行的查询结果会以Key-Value的形式保存在查询缓存中。key是SQL语句,value是查询结果。我们将这个过程称为查询缓存!

(2)Buffer Pool位于存储引擎层Buffer Pool就是MySQL存储引擎为了加速数据的读取速度而设计的缓冲机制

2、undo log日志文件(回滚日志):记录数据被修改前的样子

Innodb 存储引擎的最大特点就是支持事务,如果事务提交失败,那么该事务中所有的操作都必须回滚到执行前的样子,而这个回滚的操作,就是利用 undo log文件完成的。

  • Undo Log用于实现事务的原子性和一致性,用于撤销事务对数据的修改

上面我们介绍了,在准备更新一条SQL语句的时候,该条语句对应的数据已经被加载到 Buffer pool 中了,实际上这里还有这样的操作,就是在将该条语句加载到 Buffer Pool 中的时候同时会往 undo log 日志文件中插入一条日志,也就是将 id=1 的这条记录的原来的值记录下来,便于事务失败后进行回滚

到这一步,我们执行的 SQL 语句对应的数据已经被加载到 Buffer Pool 中了,然后开始更新这条语句,更新的操作实际是在Buffer Pool中执行的。那问题来了,更新完数据之后,Buffer Pool缓冲池中的中的数据就会和数据库中的数据库不一致,那就是说Buffer Pool 中的数据成了脏数据?没错,目前这条数据就是脏数据,Buffer Pool 中的记录是“小强”数据库中的记录是“旺财” ,这种情况 MySQL是怎么处理的呢?我们接着往下看

3、redo log 日志文件(重做日志):记录数据被修改后的样子

redo 日志文件是 InnoDB 特有的,他是存储引擎级别的

  • Redo Log用于实现事务的持久性,用于在数据库异常崩溃时恢复数据的一致性。MySQL通过Undo Log和Redo Log的配合,确保了数据库的事务安全性和持久性。

该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file)前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,供数据恢复用。

除了从磁盘中加载文件和将操作前的记录保存到 undo 日志文件中之外,其他的操作是在内存中完成的,内存中的数据的特点就是:断电丢失。如果此时 MySQL 所在的服务器宕机了,那么 Buffer Pool 中的数据会全部丢失的。这个时候 redo log 日志文件就需要来大显神通了

redo 就是准备去做、将要去做的意思,redo log 记录的是将要做的一些操作。例如,此时将要做的是 update students set stuName=‘小强’ where id=1; 那么这条操作就会被记录到 redo log buffer 中,redo log buffer 是 MySQL 为了提高效率,所以将这些操作都先放在内存中去完成

这时候假设服务器宕机了,那么缓存中的数据还是丢失了。那能不能不要放在内存中,直接保存到磁盘呢?很显然不行,在内存中操作目的是为了提高效率。如果此时 MySQL 真的宕机了,那么没关系的,因为 MySQL 会认为本次事务是失败的,会利用 undo log 的日志信息进行回滚,并不会有任何的影响。

到了这里,SQL语句也更新好了,那么需要将更新的值提交了,也就是需要提交本次的事务,只要事务成功提交了,才会将最后的变更保存到数据库。在提交事务前会将 redo Log Buffer 中的数据写入到磁盘文件 redo log 中,进行持久化,而刷入磁盘的时机则是根据 innodb_flush_log_at_trx_commit 参数来决定的:

0:表示每次事务提交时都只是把redo log留在redo log buffer中,数据库宕机有可能会丢失数据。

1(默认值):每次事务提交时,都将redo log直接持久化到磁盘,数据最安全,不会因为数据库宕机丢失数据,但是效率稍微差一点,线上系统推荐设置

2:每次事务提交时都只把redo log写到操作系统的缓存page cache里,这种情况如果数据库宕机是不会丢失数据的(os cache里还有数据),但是如果操作系统宕机了,那么page cache里的数据还没来得及写入磁盘文件就有可能会丢失数据。

InnoDB有一个后台线程,每隔1秒就会把redo log buffer中的日志,调用操作系统函数write写到文件系统page cache,然后调用操作系统函数fsync持久化到磁盘文件中。

关于这个参数的设定,需要根据具体的项目以及业务场景来定,如果设置合理那么可以带来很大的性能提升。

redo log Buffer 刷入磁盘后,就完成了数据的持久化了,就算数据库宕机了,我们也可以再下次重启的时候将 redo log 日志文件的内容恢复到 Buffer Pool 中。

前面提到,如果每次修改都直接以落盘的形式处理,那么必定有大量的随机IO,如果使用机械磁盘更会存在大量的disk seek时间,数据库性能极低,那为什么写入 redo log 就能提高性能呢?这是因为写 redo log 至磁盘属于磁盘顺序写,只需 append log 到下一位置,所以 redo log 的落盘速度是非常快的

到此SQL语句的执行就如下

1.准备SQL语句

2.MySQL会先在Buffer pool(缓冲池)中进行查找需要的数据,如果没有那么就从磁盘中取出然后放到Buffer pool中进行操作

3.在加载到Buffer pool的同时,会将这条数据的原始记录加载到undo日志文件中。

4.在Buffer Pool中完成数据操作

5.更新后的数据会记录在Redo Log Buffer中,然后根据 innodb_flush_log_at_trx_commit 参数来决定什么时候将数据刷入磁盘文件redo log进行持久化

6.MySQL重启时会将redo log恢复到缓冲池中。

4、bin log日志文件:记录整个操作过程

前言:bin log 和 redo log 有些相似,两者的主要区别有:

(1)redo log是 InnoDB 存储引擎特有的日志文件,而 bin log属于是 MySQL 级别的日志

(2)redo log 适用于崩溃恢复,bin log 适用于主从复制和数据恢复

(3)redo log 记录的东西是偏向于物理性质的,如:“对什么数据,做了什么修改”。bin log是偏向于逻辑性质的,类似于:“对 students 表中的 id 为 1 的记录租了更新操作” 。

bin log文件是如何刷入磁盘的 bin log的刷盘策略可以通过 sync_bin log 来修改,默认为0,表示先写入 os cache,也就是说在提交事务的时候,数据不会直接到磁盘中,这样如果宕机 bin log 数据仍然会丢失。所以建议将sync_bin log设置为 1,表示直接将数据写入到磁盘文件中

既然 bin log 也是日志文件,那它是在什么时候记录数据的呢?其实 MySQL 在提交事务时,不仅会将 redo log buffer 中的数据写入到 redo log 文件中,也会将本次修改的数据记录到 bin log 文件中,同时会将本次修改的 bin log 文件名和修改的内容在 bin log 中的位置记录到 redo log 中,最后还会在 redo log 最后写入 commit 标记,这样就表示本次事务被成功的提交了

如果在数据在写入 bin log文件时,刚写完,数据库宕机了,数据会丢失吗?首先可以确定的是,只要 redo log 最后没有 commit 标记,说明本次的事务一定是失败的。但是数据是没有丢失的,因为已经被记录到 redo log 的磁盘文件了,在 MySQL 重启的时候,就会将 redo log 中的数据恢复(加载)到Buffer Pool中

到目前为止,一个更新操作基本介绍得差不多,但是你有没有感觉少了哪件事情还没有做?是不是你也发现这个时候被更新记录仅仅是在内存中执行的,哪怕是宕机又恢复了也仅仅是将更新后的记录加载到 Buffer Pool 中,这个时候 MySQL 数据库中的这条记录依旧是旧值,也就是说内存中的数据在我们看来依旧是脏数据,那这个时候怎么办呢?

其实 MySQL 会有一个后台线程,它会在某个时机将我们 Buffer Pool 中的脏数据刷到 MySQL 数据库中,这样就将内存和数据库的数据保持统一了。刷新脏页的时机如下:

(1)redo log 写满时,停止所有更新操作,将 checkpoint 向前推进,推进那部分日志的脏页更新到磁盘;

(2)需要将一部分数据页淘汰,如果是干净页,直接淘汰就行了,脏页的话,需要全部同步到磁盘;

(3)mysql自认为空闲时

(4)mysql正常关闭之前

关于图中的OS cache是操作系统中内存中的一块区域,为了提升应用的写入磁盘的性能解决内存和磁盘交互的性能瓶颈。很多应用如kafka、MQ等写入硬盘的操作那么就把os cache当做硬盘来写入,提升性能。

总结

(1)首先 MySQL 执行器根据执行计划调用存储引擎的API查询数据

(2)存储引擎先从缓存池 buffer pool 中查询数据,如果没有就会去磁盘中查询,如果查询到了就将其放到缓存池中

(3)在数据加载到 Buffer Pool 的同时,会将这条数据的原始记录保存到 undo log 日志文件中

(4)innodb 会在 Buffer Pool 中执行更新操作

(5)更新后的数据会记录在 redo log buffer 中

(6)提交事务在提交的同时会做以下三件事

(7)(第一件事)将 redo log buffer 中的数据刷入到redo log文件中

(8)(第二件事)将本次操作记录写入到 bin log 文件中

(9)(第三件事)将bin log文件名字和更新内容在 bin log 中的位置记录到redo log中,同时在 redo log 最后添加 commit 标记

(10)使用一个后台线程,它会在某个时机将我们Buffer Pool中的更新后的数据刷到 MySQL 数据库中,这样就将内存和数据库的数据保持统一了

相关文章:

MySQL的底层原理与架构

前言 了解MySQL的架构和原理对于很多的后续很多的操作会有很大的帮助与理解。并且很多知识都与底层架构相关联。 了解MySQL架构 通过上面的架构图可以得知,Server层中主要由 连接器、查询缓存、解析器/分析器、优化器、执行器 几部分组成的,下面将主要…...

三极管的截止、放大、饱和区

三极管的几个区,都有什么用: 截止区:晶体管不导通,用于开关电路的“关”状态。 放大区:晶体管用于信号放大,集电极电流与基极电流成正比。 饱和区:晶体管完全导通,用于开关电路的“…...

2025-2-7-算法学习(一) 动态规划-习题1 300.最长递增子序列

文章目录 算法学习(一) 动态规划-习题1 300.最长递增子序列(1)题目(2)举例:(3)提示(4)分析(5)动态规划代码:&a…...

学习日记-250207

一.论文 1.Prompt Learning for News Recommendation 任务不一致(LLM与实际任务)产生prompt提示。 Prompt Learning for News Recommendation 论文阅读 SIGIR2023-CSDN博客 2.GPT4Rec: A Generative Framework for Personalized Recommendation and…...

【Block总结】PSA,金字塔挤压注意力,解决传统注意力机制在捕获多尺度特征时的局限性

论文信息 标题: EPSANet: An Efficient Pyramid Squeeze Attention Block on Convolutional Neural Network论文链接: arXivGitHub链接: https://github.com/murufeng/EPSANet 创新点 EPSANet提出了一种新颖的金字塔挤压注意力(PSA)模块,旨…...

代码随想录算法训练营第三十一天| 回溯算法04

491. 递增子序列 题目: 代码随想录 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 这题需要注意的点: 1. path长度在2以上才放入最终结果 2. 需要记录已经使用过的数字&am…...

pycharm集成通义灵码应用

在pycharm中安装通义灵码 1、打开files-settings 2、选中plugins-搜索”TONGYI Lingma“,点击安装 3.安装完成后在pycharm的右侧就有通义灵码的标签 4、登录账号 5、查看代码区域代码,每一个方法前面都多了通义灵码的标识,可以直接选择…...

赛博算命之 ”梅花易数“ 的 “JAVA“ 实现 ——从玄学到科学的探索

hello~朋友们!好久不见! 今天给大家带来赛博算命第三期——梅花易数的java实现 赛博算命系列文章: 周易六十四卦 掐指一算——小六壬 更多优质文章:个人主页 JAVA系列:JAVA 大佬们互三哦~互三必回!&#xf…...

【Leetcode刷题记录】54. 螺旋矩阵--模拟,以及循环条件处理的一些细节

54. 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5] 解题思路 顺时针螺旋顺序也就是“从左向…...

c++计算机教程

目的 做出-*/%计算机 要求 做出可以计算-*/%的计算机 实现 完整代码 #include<bits/stdc.h> int main() {std::cout<<"加 减- 乘* 除/ 取余% \没有了|(因为可以算三位)"<<"\n"<<"提示:每打完一个符号或打完一个数,\…...

蓝桥杯Java之输入输出练习题

题目 1&#xff1a;多组AB&#xff08;基础版&#xff09; 题目描述&#xff1a; 输入多组数据&#xff0c;每组数据包含两个整数 A 和 B&#xff0c;计算它们的和。输入以 文件结尾&#xff08;EOF&#xff09; 结束。 输入格式&#xff1a; 每行包含两个整数 A 和 B&#x…...

【R语言】环境空间

一、环境空间的特点 环境空间是一种特殊类型的变量&#xff0c;它可以像其它变量一样被分配和操作&#xff0c;还可以以参数的形式传递给函数。 R语言中环境空间具有如下3个特点&#xff1a; 1、对象名称唯一性 此特点指的是在不同的环境空间中可以有同名的变量出现&#x…...

【系统架构设计师】分布式数据库透明性

目录 1. 说明2. 分片透明3. 复制透明4. 位置透明5. 逻辑透明&#xff08;局部数据模型透明&#xff09;6.例题6.1 例题1 1. 说明 1.在分布式数据库系统中&#xff0c;分片透明、复制透明、位置透明和逻辑透明是几个重要的基本概念。2.分片透明、复制透明、位置透明和逻辑透明是…...

openpnp2.2 - 环境搭建 - 编译 + 调试 + 打包

文章目录 openpnp2.2 - 环境搭建 - 编译 调试 打包概述笔记前置任务克隆代码库切到最新的tag清理干净编译工程关掉旧工程打开已经克隆好的openpnp2.2工程将IDEA的SDK配置为openjdk23 切换中英文UI设置JAVA编译器 构建工程跑测试用例单步调试下断点导出工程的JAR包安装install…...

OpenCV:图像修复

目录 简述 1. 原理说明 1.1 Navier-Stokes方法&#xff08;INPAINT_NS&#xff09; 1.2 快速行进方法&#xff08;INPAINT_TELEA&#xff09; 2. 实现步骤 2.1 输入图像和掩膜&#xff08;Mask&#xff09; 2.2 调用cv2.inpaint()函数 2.3 完整代码示例 2.4 运行结果 …...

QT全局所有QSS样式实时切换

方法如下&#xff1a; void loadQss(int qssType) {QString name;if (qssType 1)name ":/qss/day.qss";elsename ":/qss/night.qss";QFile file(name);file.open(QFile::ReadOnly);QString qss;qss file.readAll();qApp->setStyleSheet(qss);file.…...

MySQL三大版本的演进

三大版本的演进 文章目录 三大版本的演进一&#xff1a;5.6版本&#xff08;大跃进时期&#xff09;1&#xff1a;支持只读事务2&#xff1a;innodb存储引擎增强2.1&#xff1a;缓冲池刷盘策略优化2.2&#xff1a;BufferPool缓冲池预热 3&#xff1a;新增Performance_Schema库监…...

利用 IMU 估计人体关节轴向和位置 —— 论文推导

Title: 利用 IMU 估计人体关节轴向和位置 —— “Joint axis and position estimation from inertial measurement data by exploiting kinematic constraints” —— 论文推导 文章目录 I. 论文回顾II. 铰接关节的约束1. 铰接关节约束的原理2. 铰接关节约束的梯度3. 铰接关节约…...

脚本一键生成管理下游k8s集群的kubeconfig

一、场景 1.1 需要管理下游k8s集群的场景。 1.2 不希望使用默认的cluster-admin权限的config. 二、脚本 **重点参数&#xff1a; 2.1 配置变量。 1、有单独namespace的权限和集群只读权限。 2、自签名的CA证书位置要正确。 2.2 如果配置错误&#xff0c;需要重新…...

数据库系统概念第六版记录 三

外码约束&#xff08;Foreign Key Constraint&#xff09; 外码&#xff08;Foreign Key, FK&#xff09;是关系数据库中的一个约束&#xff0c;它用于保证表之间的引用完整性。外码的值必须&#xff1a; 要么存在于被引用表的主键列中&#xff0c;要么为空&#xff08;NULL&…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...