MVCC 原理分析、MySQL是如何解决幻读的

news2024/12/23 6:32:48

文章目录

  • 一、前言回顾
    • 1.1 事务四大特性ACID
    • 1.2 并发事务问题
    • 1.3 事务隔离级别
  • 二、MVCC
    • 2.1 为什么使用MVCC
    • 2.2 基本概念——当前读、快照读、MVCC
      • 2.2.1 当前读
      • 2.2.2 快照读
      • 2.2.3 MVCC
    • 2.3 隐藏字段—— TRX_ID、ROLL_PTR
    • 2.4 undo log
      • 2.4.1 介绍
      • 2.4.2 版本链
    • 2.5 Read View读视图
    • 2.6 原理分析
      • 2.6.1 RC隔离级别
      • 2.6.2 RR隔离级别
  • 三、MySQL如何解决幻读
    • 3.1 快照读如何解决幻读
    • 3.2 当前读如何解决幻读
      • 3.2.1 记录锁 Record Lock
      • 3.2.2 间隙锁 Gap Lock
      • 3.2.3 Next-Key锁
  • 四、总结

还记得MySQL事务四大特性、并发事务问题、事务隔离级别吗?幻读又是什么呢?如果忘记可以到这里重新温习: MySQL基础:SQL分类DDL、DML、DQL、DCL;函数、约束、多表查询、事务、并发事务四大问题、事务隔离级别——脏写、脏读、不可重复读、幻读

一、前言回顾

1.1 事务四大特性ACID

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。 在事务开始和完成时,中间过程对其它事务是不可见的。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

1.2 并发事务问题

并发事务问题:脏写、脏读、不可重复读、幻读

问题描述
脏写(dirty write)两个事务同时更新一行数据,事务A回滚把事务B的值覆盖了,实质就是两个未提交的事务互相影响
脏读(dirty ready)一个事务读到另外一个事务还没有提交的数据。
不可重复读(non-repeatable read)一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。(其他事务已提交)【针对同一行记录】
幻读(phantom read)一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”【针对数据行数】
  • 脏写(dirty write):两个事务未提交的情况下,同时更新一行数据。事务A回滚,把事务B修改的值覆盖了,实质就是两个未提交的事务修改同一个值、互相影响。
  • 脏读(dirty read):指的是读到了其他事务未提交的数据。事务A修改一条数据的值,还未提交,事务B就读到了A修改的值;结果A回滚了,事务B之前读的就是一个过期值,即事务读到了修改之后没有提交的值
  • 不可重复读(non-repeatable read):指的是在一个事务内多次读取同一条数据 得到不一样的值。这个过程中可能其他事务会修改数据,并且修改之后事务都提交了。它和脏读不一样,脏读是指读取到了其他事务未提交的数据,而不可重复读表示读到了其他事务修改并提交后的值。
  • 幻读(phantom read):一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。被其他事务插入或者删除的数据影响,一个事务内同样条件的数据记录变多或者变少了

具体细节可参考 MySQL基础:SQL分类DDL、DML、DQL、DCL;函数、约束、多表查询、事务、并发事务四大问题、事务隔离级别——脏写、脏读、不可重复读、幻读

上面四个问题都是因为业务系统会多线程并发执行,每个线程可能都会开启一个事务,每个事务都会执行增删改查操作。

然后数据库会并发执行多个事务,多个事务可能会并发地对缓存页里的同一批数据进行增删改查操作,可能就会导致脏写、脏读、不可重复读、幻读这些问题。

因此这些问题的本质,就是数据库的多事务并发问题。为了解决多事务并发问题,数据库才设计了事务隔离机制、MVCC多版本隔离机制、锁机制,用一整套机制来解决多事务并发问题。

1.3 事务隔离级别

为了解决并发事务所引发的问题,在数据库中引入了事务隔离级别,且不同级别的隔离可以规避不同严重程度的事务问题。主要有以下几种:

  1. 读未提交(READ UNCOMMITTED),指一个事务还没提交,它做的修改就能被其他事务看到。
  2. 读提交(READ COMMITTED),一个事务做的修改,只有提交之后,其他事务才能看到。
  3. 可重复读(REPEATABLE READ),在整个事务过程中看到的数据,自始至终都是一致的。
  4. 串行化(SERIALIZABLE),每个读写操作都会加锁,多个事务要访问同一条记录时,必须要进行排队,优先级低的事务必须等优先级高的事务完成以后才能进行。

从1到4,隔离级别依次变高,当然,性能也依次变差。那么这些隔离级别究竟都能防止哪些问题呢

隔离级别脏读不可重复读幻读
Read uncommitted√会出现
Read committed×不会出现
Repeatable Read(MySQL默认)××
Serializable 隔离级别最高、性能最差×××

注:事务隔离级别 事务隔离级别越高,数据越安全,但是性能越低。一般采用数据库的默认级别。

MySQL InnoDB引擎默认的隔离级别是可重复读(RR)。

二、MVCC

2.1 为什么使用MVCC

在数据库并发场景中,只有读-读之间的操作才可以并发执行,读-写写-读写-写操作都要阻塞,这样就会导致 MySQL 的并发性能极差。

采用了 MVCC 机制后,只有写写之间相互阻塞,其他三种操作都可以并行,这样便提高了 MySQL 的并发性能。即 MVCC 具体解决了以下问题:

  • 并发读-写时:可以做到读操作不阻塞写操作,同时写操作也不会阻塞读操作。
  • 解决 脏读、幻读、不可重复读 等事务隔离问题,但不能解决上面的写-写(需要加锁)问题。

2.2 基本概念——当前读、快照读、MVCC

MVCC分为两种模式,一种是当前读(读取最新的数据),如 select … for update/lock in share mode、insert、update、delete;另一种是快照读(历史某个版本的数据,不一定是当前时刻最新的数据),如普通的select。具体介绍如下。

2.2.1 当前读

读取的是记录的最新版本读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读。

测试:

在这里插入图片描述

在测试中我们可以看到,即使是在默认的RR隔离级别下,事务A中依然可以读取到事务B最新提交的内容,因为在查询语句后面加上了 lock in share mode 共享锁,此时是当前读操作。当然,当我们加排他锁的时候,也是当前读操作。

2.2.2 快照读

表示不加锁的非阻塞读,像 不加锁的普通select 都属于快照读,快照读的实现基于MVCC,它读取的是记录数据的可见版本,有可能是历史某个版本的数据,不一定是当前时刻最新的数据。

  • Read Committed:每次select,都生成一个快照读。
  • Repeatable Read:开启事务后第一个select语句才是快照读的地方。
  • Serializable:快照读会退化为当前读(快照读在MySQL的串行隔离级别下会上升为当前读,即使是select操作也会加锁)。

测试见上图第4步,我们看到即使事务B提交了数据,事务A中也查询不到。 原因就是因为普通的select是快照读,而在当前默认的RR隔离级别下,开启事务后第一个select语句才是快照读的地方,后面执行相同的select语句都是从快照中获取数据,可能不是当前的最新数据,这样也就保证了可重复读。

2.2.3 MVCC

全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,即在同一时刻同一条记录在系统中可以存在多个版本。快照读为MySQL实现MVCC提供了一个非阻塞读功能。

在MySQL InnoDB中,MVCC的实现主要是为了提高数据库并发性能,它能很好地处理MySQL的读写冲突,做到尽量不加锁,大大降低系统的开销。

MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、Read View。

接下来,我们再来介绍一下InnoDB引擎的表中涉及到的隐藏字段 、undolog 以及 readview,从而来介绍一下MVCC的原理。

2.3 隐藏字段—— TRX_ID、ROLL_PTR

在这里插入图片描述

当我们创建了上面的这张表,我们在查看表结构的时候,就可以显式的看到这四个字段。 实际上除了这四个字段以外,InnoDB还会自动的给我们添加三个隐藏字段及其含义分别是:

隐藏字段含义
DB_TRX_ID最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
DB_ROLL_PTR回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
DB_ROW_ID隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

而上述的前两个字段是肯定会添加的, 是否添加最后一个字段DB_ROW_ID,得看当前表有没有主键,如果有主键,则不会添加该隐藏字段。

2.4 undo log

2.4.1 介绍

undo 日志,又叫undo log,也称回滚日志,它是InnoDB存储引擎在insert、update、delete的时候产生的便于数据回滚的日志。在数据更新之前,MySQL就需要先把更新前的数据记录到 undo log 日志中,当事务回滚时,可以利用 undo log 来进行回滚。作用包含两个——提供回滚MVCC(多版本并发控制)。undo log主要分为两种:

  • insert undo log:当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除(因为这种log只是对本事务可见,其他事务不可见,所以当事务提交后,这种类型的undo log就会被系统直接删除回收,也就是该undo log占用的undo页面链表被释放)。
  • update undo log:update、delete的时候,产生的undo log日志不仅在事务回滚时需要,在快照读时也需要(也就是MVCC),所以不能在事务提交后马上删除,只在提交后放入undo log的链表,等待purge线程进行最后的删除。

比如现在Tom的账户余额有100,现在有一个事务需要把Tom的账户余额更新为300,大致的流程如下图:

在这里插入图片描述

2.4.2 版本链

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

在这里插入图片描述

然后,有四个并发事务同时在访问这张表。

在这里插入图片描述

在这里插入图片描述

2.5 Read View读视图

Read View(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。

Read View就是事务进行快照读操作的时候产生的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统数据以及当前活跃事务的ID(就是启动了还没提交的事务)

ReadView中包含了四个核心字段:

字段含义
m_ids当前活跃的事务ID集合,活跃事务则代表是已启动但未提交的事务
min_trx_id最小活跃事务ID
max_trx_id预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
creator_trx_idReadView创建者的事务ID

在这里插入图片描述

而在readview中就规定了版本链数据的访问规则:

trx_id 代表当前undo log版本链对应事务ID。

条件是否可以访问说明
trx_id == creator_trx_id可以访问该版本成立,说明数据是当前这个事务更改的
trx_id < min_trx_id可以访问该版本成立,说明数据已经提交了
trx_id > max_trx_id不可以访问该版本成立,说明该事务是在ReadView生成后才开启
min_trx_id <= trx_id <= max_trx_id如果trx_id不在m_ids中, 是可以访问该版本的成立,说明数据已经提交

不同的隔离级别,生成ReadView的时机不同:

  • 对于使用 READ UNCOMMITTED 隔离级别的事务来说,由于可以读到未提交事务修改过的记录,所以直接读取记录的最新版本就好了

  • 对于使用 SERIALIZABLE 隔离级别的事务来说,InnoDB 使用加锁的方式来访问记录,不存在并发问题。

  • READ COMMITTED :在事务中每一次执行快照读时生成ReadView

  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,一直到提交前都复用该ReadView。在可重复读隔离级别下,Read View是在事务开始(begin)之后且执行第一条sql时创建,创建Read View的同时也就生成了一个新的事务id(直到commit结束),事务会依赖该 Read View保证查询结果保持不变直到该事务结束。

2.6 原理分析

MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。 而MVCC + 锁,则实现了事务的隔离性。 而一致性则是由redolog 与 undolog保证。

在这里插入图片描述

2.6.1 RC隔离级别

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。

我们就来分析事务5中,两次快照读读取数据,是如何获取数据的?

在这里插入图片描述

在这里插入图片描述

2.6.2 RR隔离级别

RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 而RR 是可重复读,在一个事务中,执行两次相同的select语句,查询到的结果是一样的。

那MySQL是如何做到可重复读的呢? 我们简单分析一下就知道了

在这里插入图片描述

所以呢,MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。 而MVCC + 锁,则实现了事务的隔离性。 而一致性则是由redolog 与 undolog保证。

在这里插入图片描述

三、MySQL如何解决幻读

在MySQL数据库内,默认的存储引擎是InnoDB,且事务的隔离级别是可重复读(Repeatable Read,RR)。通过上面分析我们知道,RR隔离级别下MVCC可以解决不可重复读的问题。

可重复读隔离级别没有解决幻读问题。隔离级别是RR(可重复读)下的MySQL怎么避免幻读问题呢——MySQL通过一种next-key lock的锁机制一定程度上避免了幻读问题,具体原理如下。

2.1章节已经介绍了当前读、快照读,现在我们来看看 当前读、快照读的情况下各自如何解决幻读问题?

3.1 快照读如何解决幻读

读取的并非最新数据,我们通过在事务开始生成一个快照,后面一直使用这个快照(事务会依赖该 Read View保证查询结果保持不变直到该事务结束,其他事务增加与删除数据,对于当前事务来说是不可见的),就能解决幻读,不需要额外的操作。

即在 RR 隔离级别下,MVCC 解决了在快照读情况下的幻读

(而在实际场景中,我们可能需要读取实时的数据,比如在银行业务等特殊场景下,必须是需要读取到实时的数据,此时就不能快照读,只能当前读)

3.2 当前读如何解决幻读

由于每次都是读当前,会导致一直生成新的快照。当有行数据插入或则删除时并且在查询范围之内,就会造成幻读的现象。为了解决当前读情况下出现幻读的问题,MySQL InnoDB 引擎引入了next-key lock,其等同于 记录锁+间隙锁 的组合。当执行当前读时,在锁定读取到的记录的同时,也会锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读。

next-key锁 包含两部分:

  • 记录锁(行锁,Record Lock)。锁定单个行记录的锁,防止其他事务对此行进行update和delete。加在索引上
  • 间隙锁(Gap Lock)。锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。加在索引之间

在这里插入图片描述

3.2.1 记录锁 Record Lock

Record Lock 锁住的永远是索引,不包括记录本身,即使该表上没有任何索引,那么InnoDB引擎会创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。

记录锁是有 S 锁(共享锁)和 X 锁(排他锁)之分的,当一个事务获取了一条记录的 S 型记录锁后,其他事务也可以继续获取该记录的 S 型记录锁,但不可以继续获取 X 型记录锁;当一个事务获取了一条记录的 X 型记录锁后,其他事务既不可以继续获取该记录的 S 型记录锁,也不可以继续获取 X 型记录锁。

3.2.2 间隙锁 Gap Lock

间隙锁,对索引前后的间隙上锁,不对索引本身上锁。确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读,在RR隔离级别下都支持。前开后开区间。

既然涉及到索引,那么索引对间隙锁会产生什么影响

  1. 对主键或唯一索引,如果当前读时,where 条件全部精确命中(=或in),这种场景本身就不会出现幻读,所以只会加行记录锁,也就是说间隙锁会退化为行锁(记录锁)。
  2. 非唯一索引列,如果 where 条件部分命中(>、<、like等)或者全未命中,则会加附近间隙锁。例如,某表数据如下,非唯一索引2,6,9,9,11,15。如下语句要操作非唯一索引列 9 的数据,间隙锁将会锁定的列是(6,11],该区间内无法插入数据。
  3. 对于没有索引的列,当前读操作时,会加全表间隙锁,生产环境要注意。

注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。

3.2.3 Next-Key锁

next-key lock 是索引记录上的记录锁和索引记录之前的间隙上的间隙锁的组合,包括记录本身,每个 next-key lock 是前开后闭区间(同样说明锁住的范围更大,影响并发度),也就是说间隙锁只是锁的间隙,没有锁住记录行,next-key lock 就是间隙锁基础上锁住右边界行

默认情况下,InnoDB以 REPEATABLE READ 隔离级别运行。在这种情况下,InnoDB 使用 Next-Key Lock 锁进行搜索和索引扫描,以防止幻读的发生。

以下表为例

在这里插入图片描述

假设,bank_balance表中只存在余额balance>0且主键id 为4和6的记录,那么当一个事务使用select * from where balance>0 for update查询时,其他事务就无法插入 id = 5的记录,就像是事务A把(4,6)这个范围锁住了,这就是间隙锁。

如果再把id=6的记录也同时一起锁了,合起来变成一个左开右闭区间(4, 6],那么整个区间锁也叫next-key lock。

当事务A执行select * from bank_balance where balance > 0 for update这条锁定读语句后,就会把整个表所有记录锁上(因为balance字段无索引),并根据主键id和表记录形成多个next-key lock; 此时如果事务B执行insert语句将会被阻塞,直到事务A提交了 事务B才会执行。这就避免了上述所说的幻读问题。

四、总结

1)事务四大特性ACID:原子性、一致性、隔离性、持久性

2)并发事务问题:脏写、脏读、不可重复读、幻读

3)事务隔离级别:读未提交(READ UNCOMMITTED)、读提交(READ COMMITTED)、可重复读(REPEATABLE READ)、串行化(SERIALIZABLE)

4)MVCC 在可重复读(RR)隔离级别下 解决了以下问题:

  • 并发读-写时:可以做到读操作不阻塞写操作,同时写操作也不会阻塞读操作。
  • 解决 脏读、幻读、不可重复读 等事务隔离问题,但不能解决写-写(需要加锁)问题。

5)当前读与快照读:MVCC分为两种模式,一种是当前读(读取最新的数据),如 select … for update/lock in share mode、insert、update、delete;另一种是快照读(历史某个版本的数据,不一定是当前时刻最新的数据),不加锁的普通select 都属于快照读

6)MVCC原理:MVCC的具体实现,需要依赖于数据库记录中的三个隐式字段(TRX_ID、ROLL_PTR)、undo log日志、Read View

7)Read View读视图:Read View 是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统数据以及当前活跃事务的ID(未提交的)。Read View也规定了版本链数据的访问规则

8)不同的隔离级别,生成ReadView的时机不同:

  • READ COMMITTED :在事务中每一次执行快照读(不加锁的普通select)时生成ReadView
  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,一直到提交前都复用该ReadView,事务会依赖该 Read View保证查询结果保持不变直到该事务结束。

9)RR隔离级别如何解决幻读问题快照读依靠MVCC控制,当前读通过 next-key lock 解决(MVCC 解决了快照读情况下的幻读,next-key lock 解决当前读情况下的幻读)。

10)间隙锁和行锁合称 Next-Key Lock,每个 Next-Key Lock 是前开后闭区间。当执行当前读时,在锁定读取到的记录的同时,也会锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读。

参考 黑马程序员MySQL相关视频笔记、美团面试官:可重复读隔离级别实现原理是什么?(一文搞懂MVCC机制)、MySQL 如何解决幻读(MVCC 原理分析)

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

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

相关文章

tensorflow2.0 -- 介绍及环境配置

文章目录 机器学习的框架tensorflow 2.0环境配置 机器学习的框架 scikit-learn, 传统的机器学习框架&#xff0c;不支持深度学习和GPU加速计算&#xff1b; caffe, 深度学习框架&#xff0c;发展到pytorch keras, 深度学习的包裹器 tensorflow&#xff0c;google开源的深度学习…

【Linux部署】【pig前端部署】Linux安装- docker/docker-compose/nginx (使用docker优雅部署nginx)

&#x1f338;&#x1f338; Linux安装- docker/docker-compose/nginx 优雅部署 &#x1f338;&#x1f338; 一、一键安装jdk yum install -y java-1.8.0-openjdk.x86_64验证 二、安装docker yum list docker-ce --showduplicates | sort -rsudo yum install -y yum-utils …

RocketMq局部顺序消息

package com.ldj.rocketmq.producer;import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.common.message.Message;import java.nio.charset.StandardCharsets;/*** User: ldj* Date: 2024/5/26* Time: 15:09* Description: 局部顺序消…

深度神经网络——什么是生成式人工智能?

1.引言 生成式人工智能最近引起了很大的关注。 该术语用于指依赖无监督或半监督学习算法来创建新的数字图像、视频、音频和文本的任何类型的人工智能系统。 麻省理工学院表示&#xff0c;生成式人工智能是过去十年人工智能领域最有前途的进展之一。 通过生成式人工智能&#…

队列(C语言)

文章目录 [TOC](文章目录) 前言1.队列的概念及结构2.队列的实现3.相关操作的具体实现3.1.初始化队列(QueueInit)和销毁队列(QueueDestory)3.2.队尾入队(QueuePush)和队头出队(QueuePop)3.3.判空(QueueEmpty)、获得队尾元素(QueueBack)以及获得队头元素(QueueFront) 前言 前面我…

打卡信奥刷题(20)用Scratch图形化工具信奥B3756 [信息与未来 2021] 幸运数字

本题的基础是进制转换&#xff0c;关于2进制转换可以参考打卡信奥刷题&#xff08;19&#xff09;用Scratch图形化工具信奥B3972 [语言月赛 202405] 二进制 题解 知道了2进制&#xff0c;来实现5进制、7进制、9进制是一样的。 [信息与未来 2021] 幸运数字 题目描述 如果⼀个…

内存的基本知识与连续分配管理

目录 一. 内存的基础知识1.1. 什么是内存1.2 指令的工作原理1.2.1 装入的三种方式 - 绝对装入1.2.2 可重定位装入1.2.3 动态重定位装入1.3 从写程序到程序运行 二. 基本内存管理的概念三. 覆盖与交换3.1 覆盖技术3.2 交换技术 四. 连续分配管理方式4.1 单一连续分配4.2 固定分区…

【全开源】赛事报名系统源码(Fastadmin+ThinkPHP和Uniapp)

基于FastadminThinkPHP和Uniapp开发的赛事报名系统&#xff0c;包含个人报名和团队报名、成绩查询、成绩证书等。 构建高效便捷的赛事参与平台 一、引言&#xff1a;赛事报名系统的重要性 在举办各类赛事时&#xff0c;一个高效便捷的报名系统对于组织者和参与者来说都至关重…

前后端部署笔记

windows版&#xff1a; 如果傻呗公司让用win电脑部署&#xff0c;类似于我们使用笔记本做局域网服务器&#xff0c;社内使用。 1.安装win版的nginx、mysql、node、jdk等 2.nginx开机自启参考Nginx配置及开机自启动&#xff08;Windows环境&#xff09;_nginx开机自启动 wind…

mapboxGL中山体背景+边界阴影的一种实现方案

概述 很多地图可视化的项目中有要求实现如下的效果&#xff0c;本文借助QGIS、PS和turf.js&#xff0c;在mapboxGL中实现山体背景&#xff0b;边界阴影的效果。 实现效果 实现 1. 需要数据 要实现这样的效果&#xff0c;我们需要如下数据&#xff1a; 山体背景图地级市数据…

[卷积神经网络]RepConv和重参数化

RepConv是Yolov7,YoloV9中一个重要的结构&#xff0c;其主要用于在保持精度不退化的情况下提升推理速度。RepConv在学习阶段和推理阶段拥有不同的结构&#xff0c;这使得其推理阶段的复杂度大大降低。这项技术的核心在于重参数化。 一、重参数化 重参数化的主要思想是将卷积(C…

2024年弘连网络FIC大会竞赛题线下决赛题

总结&#xff1a; FIC决赛的时候&#xff0c;很多小问题没发现&#xff0c;在pve平台做题确实很方便。 这套题目复盘完&#xff0c;服务器这块的知识确实收获了很多&#xff0c;对pve集群平台和网络拓扑也有了一定的认识&#xff0c;感谢各位大佬悉心指导。 接下来&#xff0…

工具使用-网络性能测试工具(iperf)-TCP 和 UDP 的吞吐量-包转发率参数的理解

时间戳&#xff1a;2024年5月26日15:18:39 iperf 和 netperf 都是最常用的网络性能测试工具&#xff0c;测试 TCP 和 UDP 的吞吐量。它们都以客户端和服务器通信的方式&#xff0c;测试一段时间内的平均吞吐量。 接下来&#xff0c;我们就以 iperf 为例&#xff0c;看一下 TC…

C语言PTA练习题:三角形类别,输入三角形三条边,求面积,四则计算器,猴子吃桃

7-1 三角形类别 输入三个整数&#xff0c;以这三个数为边长&#xff0c;判断是否构成三角形&#xff1b;若不能输出"no"&#xff0c;若构成三角形&#xff0c;进一步判断它们构的是&#xff1a;锐角三角形或直角三角形或钝角三角形.分别输出"ruijiao",&qu…

Spring MVC+mybatis项目入门:旅游网(四)用户注册——mybatis的配置与使用以及Spring MVC重定向

个人博客&#xff1a;Spring MVCmybatis项目入门:旅游网&#xff08;四&#xff09;用户注册2-持久化 | iwtss blog 先看这个&#xff01; 这是18年的文章&#xff0c;回收站里恢复的&#xff0c;现阶段看基本是没有参考意义的&#xff0c;技术老旧脱离时代&#xff08;2024年…

qt-C++笔记之QThread使用

qt-C笔记之QThread使用 ——2024-05-26 下午 code review! 参考博文&#xff1a; qt-C笔记之使用QtConcurrent异步地执行槽函数中的内容&#xff0c;使其不阻塞主界面 qt-C笔记之QThread使用 文章目录 qt-C笔记之QThread使用一:Qt中几种多线程方法1.1. 使用 QThread 和 Lambda…

【二叉树】LeetCode.144:二叉树的前序遍历(小细节把握)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;初阶初阶结构刷题 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 1.题目描述&#xff1a;​编辑 2.问题分析&#xff1a; &#x1f354;函数解读&#xff1a; …

功率电感的设计步骤

文章目录 1&#xff1a;高导磁气隙&#xff08;铁氧体&#xff09;1.1设计原理1.2 设计步骤 2 铁粉芯2.1&#xff1a;设计原理2.2&#xff1a;设计步骤 TI电感设计 学习视频原链接 截图 1 截图1 截图1 截图 2 截图2 截图2 1&#xff1a;高导磁气隙&#xff08;铁氧体&#…

solidworks画螺栓学习笔记

螺栓 单位mm 六边形 直径16mm 水平约束 拉伸 选择厚度6mm 拉伸切除 画相切圆 切除厚度6mm&#xff0c;反向切除 &#xff0c;拔模角度45 螺栓 直径9mm&#xff0c;长度30mm 倒角 直径1mm&#xff0c;角度45 异形孔向导 螺纹线 偏移打勾&#xff0c;距离为2mm&#…

【C语言】八进制、十六进制

前言 在我们日常生活中使用的数往往是十进制的&#xff0c;而当我们学习C语言后我们会接触到许多不同的进制并且时常需要去思考与使用这些不同的进制&#xff08;尤其是2的幂相关的进制&#xff0c;因为这种计数系统比十进制更接近于计算机的二进制系统&#xff09;&#xff0…