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

文章目录

  • 一、前言回顾
    • 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.mzph.cn/pingmian/15718.shtml

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

相关文章

python写接口性能测试

import time import requestsdef measure_response_time(api_url):try:start_time time.time()response requests.get(api_url, timeout10) # 设置超时时间为10秒end_time time.time()response_time end_time - start_timeprint(f"接口 {api_url} 的响应时间为&#…

读书笔记-Java并发编程的艺术-第1章 并发编程的挑战

文章目录 1.1 上下文切换1.1.1 多线程一定快吗1.1.2 如何减少上下文切换 1.2 死锁1.3 资源限制的挑战 1.1 上下文切换 即时是单核处理器也支持多线程执行代码&#xff0c;CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给多个线程的时间&#xff0c;因为时间…

C++拓展之scanf和printf

scanf和printf&#xff0c;这东西&#xff0c;说难也不难&#xff0c;可一旦深入学&#xff0c;学两天都可能学不完。 为了输入输出&#xff0c;我们要把这些占位符学一学。 我们来看看AI是怎么回答的。 Q&#xff1a;C格式化占位符有哪些&#xff1f; A&#xff1a;C中常用的…

【手把手带你搓组件库】从零开始实现Element Plus

从零开始实现Element Plus 前言亮点项目搭建1、创建项目初始化monorepo创建 .gitignore目录结构安装基础依赖配置文件创建各个分包入口utilscomponentscoreplaytheme 2、创建VitePress文档3、部署到Github Actions生成 GH_TOKENGitHub Page 演示 4、总结 前言 在本文中&#xf…

面向可复用性和可维护性的设计模式 课程学习总结

什么是设计模式 设计模式&#xff1a;在软件设计中给定上下文中常见问题的通用的、可重用的解决方案。 设计模式分类 1. 创建型模式——Creational patterns 关注对象创建的过程 1.1 工厂方法模式 定义用于创建对象的接口&#xff0c;但让子类决定要实例化哪个类。工厂方…

4.Redis之Redis的通用命令

0.Redis 实战操作 通过 redis-cli 客户端和 redis 服务器交互 涉及到很多的 redis 的命令 【redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习) 2.学会使用 redis 的文档-> 阅读文档, 是程序猿的基操!! redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习…

部署CNI网络组件+k8s多master集群部署+负载均衡

一、环境部署 主机服务 192.168.91.5 K8S集群master01192.168.91.8 K8S集群master02192.168.91.6K8S集群node01192.168.91.7K8S集群node02192.168.91.9 负载均衡nginxkeepalive01&#xff08;master&#xff09;192.168.91.10 负载均衡nginxkeepalive02&#xff08;backup&am…

编程实战:自己编写HTTP服务器(系列3:处理框架)

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 系列入口&#xff1a;编程实战…

TypeScript学习日志-第三十二天(infer关键字)

infer关键字 一、作用与使用 infer 的作用就是推导泛型参数&#xff0c;infer 声明只能出现在 extends 子语句中&#xff0c;使用如下&#xff1a; 可以看出 已经推导出类型是 User 了 二、协变 infer 的 协变会返回联合类型&#xff0c;如图&#xff1a; 三、逆变 infer…

pikachu靶场中的CSRF、SSRF通关

目录 1、CSRF介绍 2、CSRF&#xff08;get&#xff09; 3、CSRF&#xff08;post&#xff09; 4、CSRF Token 5、SSRF介绍 6、SSRF&#xff08;curl&#xff09; 7、SSRF&#xff08;file_get-content&#xff09; 8、CSRF与SSRF的区别 最近在学习CSRF、SSRF漏洞&#…

Boyer-Moore投票算法

摩尔投票法&#xff0c;又称为博耶-摩尔多数投票算法&#xff0c;是一种用于在一组数据中寻找多数元素(出现次数超过一半的元素)的算法。该算法的效率非常高&#xff0c;时间复杂度为O(n)&#xff0c;空间复杂度为O(1)&#xff0c;适合处理大数据量的情况。 步骤 首先定义两个…

飞机大战游戏实现揭秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、游戏概览与核心玩法 二、游戏模块详解 1. 游戏主循环模块 2. 创建初始化模块 三、关…

美军配备人工智能武器的机器狗引发伦理争议

近日&#xff0c;美国海军陆战队特种作战司令部&#xff08;MARSOC&#xff09;的一项测试引发了全球关注&#xff1a;他们正在评估一种由“幽灵机器人”公司研发的最新型机器狗&#xff0c;并考虑为其配备“玛瑙工业”公司提供的武器系统。这一消息犹如在平静的湖面投下一颗石…

Python 之 日志巡检脚本

脚本说明 使用Paramiko库进行SSH连接的自动化脚本&#xff0c;用于检查、配置和排除设备故障。说明如下&#xff1a; 导入所需的库&#xff1a;paramiko、json、logging和concurrent.futures。定义配置文件路径&#xff08;devices.json&#xff09;和日志文件路径&#xff0…

阿里巴巴最新研究突破:自我演化大模型,打破性能天花板

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读AI论文解读 原创作者 | 柏企 引言&#xff1a;自我进化的新篇章 在人工智能领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展正迎来一场革命性的变革。传统的训练模式依赖…

006、API_单线程

Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库 服务&#xff0c;本节首先通过多个客户端命令调用的例子说明Redis单线程命令处理 机制&#xff0c;接着分析Redis单线程模型为什么性能如此之高&#xff0c;最终给出为什么理 解单线程模型是使用和运维Redis的…

WordPress国外超人气主题Vikinger汉化版

WordPress国外超人气主题Vikinger汉化版 前言效果图安装教程领取主题下期更新预报 前言 我们在上一个教程已经学过如何安装WordPress&#xff0c;所以现在不用多说。 效果图 安装教程 下载后先本地解压&#xff0c;找到vikinger.zip文件&#xff0c;上传安装并启用主题。 访…

EasyMR 基于国产化信创的适配实践技术详解

国产化信创&#xff0c;即采用国产信息技术产品和服务&#xff0c;构建自主可控的信息技术体系。近年来&#xff0c;随着国家对网络安全和信息安全的重视程度不断提高&#xff0c;国产化信创已经成为国家战略的重要组成部分&#xff0c;并呈现出以下大趋势&#xff1a; ● 政策…

【C语言】C语言-学生选修课程系统(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

分享几张漂亮的linux kde主题

分享几张漂亮的linux kde主题&#xff1a;在系统设置的全局主题内下载。