⛳ MVCC 原理详解

news2024/5/18 11:53:41

🎍目录

  • ⛳ MVCC 原理详解
    • 🐾 一、事务回顾
      • 📐 1.1、什么是数据库事务,为什么要有事务
      • 🎉 1.2、事务包括哪几个特性?
      • 🎍 1.3、事务并发存在的问题
        • 1.3.1、脏读
        • 1.3.2、不可重复读
        • 1.3.3、幻读
      • 🎒 1.4 四大隔离级别
        • 1.4.1 读未提交
        • 1.4.2 读已提交
        • 1.4 3 可重复读
        • 1.4.4 串行化
      • 🎃 1.5、MySQL数据库是如何保证事务的隔离性的呢?
    • 🏭 二、什么是 MVCC ?
    • 🎨 三、MVCC 实现的关键知识点
      • 🏭 3.1、事务版本号
      • 👣 3.2、隐式字段
      • 🐾 3.3、undo log
      • 📝 3.4、版本链
      • 💭 3.5、快照和当前读
      • 🏀 3.6、Reader View
    • 🎁 四、MVCC的演示过程

⛳ MVCC 原理详解

🐾 一、事务回顾

📐 1.1、什么是数据库事务,为什么要有事务

事务,由一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。

假如 A 转账给 B 100 元,先从 A 的账户里扣除 100 元,再在 B 的账户上加上 100 元。如果扣完 A 的 100 元后,还没来得及给 B 加上,银行系统异常了,最后导致 A 的余额减少了,B 的余额却没有增加。所以就需要事务,将 A 的钱回滚回去,就是这么简单。

为什么要有事务呢? 就是为了保证数据的最终一致性。

🎉 1.2、事务包括哪几个特性?

事务四个典型特性,即 ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部都执行,要么都不执行。
  • 一致性:指在事务开始之前和事务结束以后,数据不会被破坏,假如 A 账户给 B 账户转 10 块钱,不管成功与否,A 和 B 的总金额是不变的。
  • 隔离性:多个事务并发访问时,事务之间是相互隔离的,一个事务不应该被其他事务干扰,多个并发事务之间要相互隔离。
  • 持久性:表示事务完成提交后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。

🎍 1.3、事务并发存在的问题

事务并发会引起脏读、不可重复读、幻读问题;

1.3.1、脏读

如果一个事务读取到了另一个未提交事务修改过的数据,我们就称发生了脏读现象。

假设现在有两个事务 A、B :

  1. 假设现在 Jay 的余额是 100 ,事务 A 正在准备查询 Jay 的余额;
  2. 事务 B 先扣减 Jay 的余额,扣了 10 ,但是还没提交;
  3. 最后 A 读到的余额是 90 ,即扣减后的余额;

image-20230829204656632

**脏读:**因为事务 A 读取到事务 B 未提交的数据,这就是脏读。

1.3.2、不可重复读

同一个事务内,前后多次读取,读取到的数据内容不一致;

假设现在有两个事务 A 和 B:

  • 事务 A 先查询 Jay 的余额,查到结果是 100
  • 这时候事务 B 对 Jay 的账户余额进行扣减,扣去 10 后,提交事务
  • 事务 A 再去查询 Jay 的账户余额发现变成了 90

image-20230829205204066

不可重复读:事务 A 被事务 B 干扰到了!在事务 A 范围内,两个相同的查询,读取同一条记录,却返回了不同的数据,这就是不可重复读

1.3.3、幻读

如果一个事务先根据某些搜索条件查询出一些记录,在该事务未提交时,另一个事务写入了一些符合那些搜索条件的记录(如 insert、delete、update),就意味着发生了幻读

假设现在有两个事务 A、B:

  • 事务 A 先查询 id 大于 2 的账户记录,得到记录 id=2 和 id=3 的两条记录
  • 这时候,事务 B 开启,插入一条 id=4 的记录,并且提交了
  • 事务 A 再去执行相同的查询,却得到了 id=2,3,4 的 3 条记录了。

image-20230829205502421

**幻读:**事务 A 查询一个范围的结果集,另一个并发事务 B 往这个范围中插入新的数据,并提交事务,然后事务 A 再次查询相同的范围,两次读取到的结果集却不一样了,这就是幻读。

🎒 1.4 四大隔离级别

问题:四大隔离级别,都会存在哪些并发问题?

为了解决并发事务存在的脏读、不可重复读、幻读等问题,数据库大叔设计了四种隔离级别。分别是读未提交,读已提交,可重复读,串行化(Serializable)

image-20230829205600936

  • Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READ COMMITED
  • Mysql 支持 4 种事务隔离级别。Mysql 默认的事务隔离级别为: REPEATABLE READ。

1.4.1 读未提交

读未提交隔离级别,只限制了两个数据不能同时修改,但是修改数据的时候,即使事务未提交,都是可以被别的事务读取到的,这级别的事务隔离有脏读、不可重复读、幻读的问题;

1.4.2 读已提交

读已提交隔离级别,当前事务只能读取到其他事务提交的数据,所以这种事务的隔离级别解决了脏读问题,但还是会存在不可重复读、幻读问题;

1.4 3 可重复读

可重复读隔离级别,限制了读取数据的时候,不可以进行修改,所以解决了不可重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题;

1.4.4 串行化

事务最高的隔离级别,在该级别下,所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

🎃 1.5、MySQL数据库是如何保证事务的隔离性的呢?

数据库是通过加锁,来实现事务的隔离性的。这就好像,如果你想一个人静静,不被别人打扰,你就可以在房门上加上一把锁。

加锁确实好使,可以保证隔离性。比如串行化隔离级别就是加锁实现的。但是频繁的加锁,导致读数据时,没办法修改,修改数据时,没办法读取,大大降低了数据库性能

那么,如何解决加锁后的性能问题的?

答案就是,MVCC 多版本并发控制!它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。

🏭 二、什么是 MVCC ?

MVCC 体现了两种思想:

  1. MVCC 是 写时复制(copy on writer)思想的一种体现
  2. MVCC 是 以空间换时间 思想的一种体现;

MVCC (Muti-Version Concurrency Control )多版本并发控制,是用来在数据库中控制并发的⽅法,实现对数据库的并发访问⽤的,就是⼀种写时复制的思想的应⽤。在MySQL中,MVCC只在读取已提交(Read Committed)和可重复读(Repeatable Read)两个事务级别下有效。其是通过Undo⽇志中的版本链和ReadView⼀致性视图来实现的。MVCC就是在多个事务同时存在时,SELECT语句找寻到具体是版本链上的哪个版本,然后在找到的版本上返回其中所记录的数据的过程。

⾸先需要知道的是,在MySQL中,会默认为我们的表后⾯添加三个隐藏字段:

  • DB_ROW_ID:⾏ID,MySQL的B+树索引特性要求每个表必须要有⼀个主键。如果没有设置的话,会⾃动寻找第⼀个不包含NULL的唯⼀索引列作为主键。如果还是找不到,就会在这个DB_ROW_ID上⾃动⽣成⼀个唯⼀值,以此来当作主键(该列和MVCC的关系不⼤);
  • DB_TRX_ID:事务ID,记录的是当前事务在做INSERT或UPDATE语句操作时的事务ID(DELETE语句被当做是UPDATE语句的特殊情况,后⾯会进⾏说明);
  • DB_ROLL_PTR:回滚指针,通过它可以将不同的版本串联起来,形成版本链。相当于链表的next指针。

数据库中同时存在多个版本的数据,并不是整个数据库的多个版本,而是某一条记录的多个版本同时存在,在某个事务对其进行操作的时候,需要查看这一条记录的隐藏列事务版本 id,比对事务 id 并根据事物隔离级别去判断读取哪个版本的数据。

🎨 三、MVCC 实现的关键知识点

🏭 3.1、事务版本号

事务每次开启前,都会从数据库获得一个自增长的事务ID,可以从事务ID判断失误的执行先后顺序。这就是事务版本号。

👣 3.2、隐式字段

对于 InnoDB 存储引擎,每一行记录都有两个隐藏列 trx_idroll_pointer,如果表中没有主键和非 NULL 唯一键时,则还会有第三个隐藏的主键列 row_id

🐾 3.3、undo log

undo log,回滚日志,用于记录数据被修改前的信息。在表记录修改之前,会先把数据拷贝到 undo log 里,如果事务回滚,即可以通过 undo log 来还原数据。

直接上有种后悔药叫undo log

可以这样认为,当 delete 一条记录时,undo log 中会记录一条对应的 insert 记录,当 update 一条记录时,它记录一条对应相反的 update 记录。

undo log 有什么用途呢?

  1. 事务回滚时,保证原子性和一致性。
  2. 用于 MVCC 快照读

📝 3.4、版本链

多个事务并行操作某一行数据时,不同事务对该行数据的修改会产生多个版本,然后通过回滚指针(roll_pointer),连成一个链表,这个链表就称为版本链。如下:

image-20230906200129554

其实,通过版本链,我们就可以看出事务版本号、表格隐藏的列和 undo log 它们之间的关系。我们再来小分析一下。

  1. 假设现在有一张 core_user 表,表里面有一条数据,id 为 1,名字为孙权:

    image-20230906200223989

  2. 现在开启一个事务 A:对 core_user 表执行update core_user set name ="曹操" where id=1,会进行如下流程操作

    • 首先获得一个事务 ID=100
    • 把 core_user 表修改前的数据,拷贝到 undo log
    • 修改 core_user 表中,id=1 的数据,名字改为曹操
    • 把修改后的数据事务 Id=101 改成当前事务版本号,并把 roll_pointer 指向 undo log 数据地址。

    image-20230906200420149

💭 3.5、快照和当前读

快照读: 读取的是记录数据的可见版本(有旧的版本)。不加锁,普通的 select 语句都是快照读,如:

select * from core_user where id > 2;

当前读:读取的是记录数据的最新版本,显式加锁的都是当前读

select * from core_user where id > 2 for update;
select * from account where id>2 lock in share mode;

🏀 3.6、Reader View

Read View 是什么呢? 它就是事务执行 SQL 语句时,产生的读视图。实际上在 innodb 中,每个 SQL 语句执行前都会得到一个 Read View。

Read View 有什么用呢? 它主要是用来做可见性判断的,即判断当前事务可见哪个版本的数据~

Read View 是如何保证可见性判断的呢?我们先看看 Read view 的几个重要属性

  • m_ids:当前系统中那些活跃(未提交)的读写事务 ID, 它数据结构为一个 List。
  • min_limit_id:表示在生成 Read View 时,当前系统中活跃的读写事务中最小的事务 id,即 m_ids 中的最小值。
  • max_limit_id:表示生成 Read View 时,系统中应该分配给下一个事务的 id 值。
  • creator_trx_id: 创建当前 Read View 的事务 ID

image-20230906200957129

(其中min_id指向ReadView中未提交事务数组中的最⼩事务ID,⽽max_id指向ReadView中的已经创建的最⼤事务ID)

  • 如果落在绿⾊区间(DB_TRX_ID < min_id):这个版本⽐min_id还⼩(事务ID是从⼩往⼤顺序⽣成的),说明这个版本在SELECT之前就已经提交了,所以这个数据是可⻅的。或者(这⾥是短路或,前⾯条件不满⾜才会判断后⾯这个条件)这个版本的事务本身就是当前SELECT语句所在事务的话,也是⼀样可⻅的;
  • 如果落在红⾊区间(DB_TRX_ID > max_id):表示这个版本是由将来启动的事务来⽣成的,当前还未开始,那么是不可⻅的;
  • 如果落在⻩⾊区间(min_id <= DB_TRX_ID <= max_id):这个时候就需要再判断两种情况:
    • 如果这个版本的事务ID在ReadView的未提交事务数组中,表示这个版本是由还未提交的事务⽣成的,那么就是不可⻅的;
    • 如果这个版本的事务ID不在ReadView的未提交事务数组中,表示这个版本是已经提交了的事务⽣成的,那么是可⻅的。

如果在上述的判断中发现当前版本是不可⻅的,那么就继续从版本链中通过回滚指针拿取下⼀个版本来进⾏上述的判断。

🎁 四、MVCC的演示过程

下⾯通过⼀个示例来具体演示MVCC的执⾏过程(假设是在可重复读事务级别下),当前account表中已经有了⼀条初始数据(id=1,name=monkey):

image-20230906201549902

image-20230906201619674

从左往右分别是五个事务,从上到下是时刻点。其中在第2和3时刻点中事务100和事务200(这⾥两个事务之间相差100只是为了更加⽅便去看,正常来说下个事务的ID是以+1的⽅式来创建的)分别执⾏了⼀条UPDATE语句,这两条语句并⽆实际作⽤,只是为了⽣成事务ID的,所以在下⾯的MVCC执⾏过程中就不分析这两条语句所带来的影响了,我们只研究account表。⽽其中最后两个事务,我是注明没有事务ID的。因为事务ID是执⾏⼀条更新操作(增删改)的语句后才会⽣成(这也是事务100和事务200要先执⾏5⼀条更新语句的意义),并不是开启事务的时候就会⽣成。最后两个事务中可以看到就是执⾏了⼀些SELECT语句⽽已,所以它们并没有事务ID。

⾸先来看⼀下初始状态时的版本链和ReadView(ReadView此时还未⽣成):

image-20230906201730417

其中事务1在account表中创建了⼀条初始数据。
之后在第1时刻点,五个事务分别开启了事务(如上所说,这个时候还没有⽣成事务ID)。

在第2时刻点,第⼀个事务执⾏了⼀条UPDATE语句,⽣成了事务ID为100。

在第3时刻点,第⼆个事务执⾏了⼀条UPDATE语句,⽣成了事务ID为200。

在第4时刻点,第三个事务执⾏了⼀条UPDATE语句,将account表中id为1的name改为了monkey301。同时⽣成了事务ID为300。

在第5时刻点,事务300也就是上⾯的事务执⾏了commit操作。

在第6时刻点,第四个事务执⾏了⼀条SELECT语句,想要查询⼀下当前id为1的数据(如上所说,该事务没有⽣成事务ID)。此时的版本链和ReadView如下:

image-20230906201812253

因为在第5时刻点,事务300已经commit了,所以ReadView的未提交事务数组中不包含它。此时根据上⾯所说的⽐对规则,拿版本链中的第⼀个版本的事务ID为300进⾏⽐对,⾸先当前这条SELECT语句没有在事务300中进⾏查询,然后发现是落在⻩⾊区间,⽽且事务300也没有在ReadView的未提交事务数组中,所以是可⻅的。即此时在第6时刻点,第四个事务所查找到的结果是monkey301。

在第7时刻点,事务100执⾏了⼀条UPDATE语句,将account表中id为1的name改为了monkey101。

在第8时刻点,事务100⼜执⾏了⼀条UPDATE语句,将account表中id为1的name改为了monkey102。

在第9时刻点,第四个事务执⾏了⼀条SELECT语句,想要查询⼀下当前id为1的数据。此时的版本链和ReadView如下:

image-20230906201857493

注意,因为当前是在可重复读的事务级别下,所以此时的ReadView沿⽤了在第6时刻点⽣成的ReadView(如果是在读取已提交的事务级别下,此时就会重新⽣成⼀份ReadView了)。然后根据上⾯所说的⽐对规则,拿版本链中的第⼀个版本的事务ID为100进⾏⽐对,⾸先当前这条SELECT语句没有在事务100中进⾏查询,然后发现是落在⻩⾊区间,⽽且事务100是在ReadView的未提交事务数组中,所以是不可⻅的。此时通过回滚指针拿取下⼀个版本,发现事务ID仍然为100,经过分析后还是不可⻅的。此时⼜拿取下⼀个版本:事务ID为300进⾏⽐对,⾸先当前这条SELECT语句没有在事务300中进⾏查询,然后发现是落在⻩⾊区间,但是事务300没有在ReadView的未提交事务数组中,所以是可⻅的。即此时在第9时刻点,第四个事务所查找到的结果仍然是monkey301(这也就是可重复读的含义)。

在第10时刻点,事务100commit提交事务了。同时事务200执⾏了⼀条UPDATE语句,将account表中id为1的name改为了monkey201。

在第11时刻点,事务200⼜执⾏了⼀条UPDATE语句,将account表中id为1的name改为了monkey202。

在第12时刻点,第四个事务执⾏了⼀条SELECT语句,想要查询⼀下当前id为1的数据。此时的版本链和ReadView如下:

image-20230906201951550

跟第9时刻点⼀样,在可重复读的事务级别下,ReadView沿⽤了在第6时刻点⽣成的ReadView。然后根据上⾯所说的⽐对规则,拿版本链中的第⼀个版本的事务ID为200进⾏⽐对,⾸先当前这条SELECT语句没有在事务200中进⾏查询,然后发现是落在⻩⾊区间,⽽且事务200是在ReadView的未提交事务数组中,所以是不可⻅的。此时通过回滚指针拿取下⼀个版本,发现事务ID仍然为200,经过分析后还是不可⻅的。此时⼜拿取下⼀个版本:事务ID为100进⾏⽐对,⾸先当前这条SELECT语句没有在事务100中进⾏查询,然后发现是落在⻩⾊区间内,同时在ReadView的未提交数组中,所以依然是不可⻅的。此时⼜拿取下⼀个版本,发现事务ID仍然为100,经过分析后还是不可⻅的。此时再拿取下⼀个版本:事务ID为300进⾏⽐对,⾸先当前这条SELECT语句没有在事务300中进⾏查询,然后发现是落在⻩⾊区间,但是事务300没有在ReadView的未提交事务数组中,所以是可⻅的。即此时在第12时刻点,第四个事务所查找到的结果仍然是monkey301。

同时在第12时刻点,第五个事务执⾏了⼀条SELECT语句,想要查询⼀下当前id为1的数据。此时的版本链和ReadView如下:

image-20230906202053337

注意,此时第五个事务因为是该事务内的第⼀条SELECT语句,所以会重新⽣成在当前情况下的ReadView,即上图中所示的内容。可以看到,和第四个事务⽣成的ReadView并不⼀样,因为在之前的第10时刻点,事务100已经提交事务了。然后根据上⾯所说的⽐对规则,拿版本链中的第⼀个版本的事务ID为200进⾏⽐对,⾸先当前这条SELECT语句没有在事务200中进⾏查询,然后发现是落在⻩⾊区间,⽽且事务200是在ReadView的未提交事务数组中,所以是不可⻅的。此时通过回滚指针拿取下⼀个版本,发现事务ID仍然为200,经过分析后还是不可⻅的。此时⼜拿取下⼀个版本:事务ID为100进⾏⽐对,发现是在绿⾊区间,所以是可⻅的。即此时在第12时刻点,第五个事务所查找到的结果是monkey102(可以看到,即使是同⼀条SELECT语句,在不同的事务中,查询出来的结果也可能是不同的,究其原因就是因为ReadView的不同)。

在第13时刻点,事务200执⾏了commit操作,整段分析过程结束。

以上演示的就是MVCC的具体执⾏过程,在多个事务下,版本链和ReadView是如何配合进⾏查找的。上⾯还遗漏了⼀种情况没有进⾏说明,就是如果是DELETE语句的话,也会在版本链上将最新的数据插⼊⼀份,然后将事务ID赋值为当前进⾏删除操作的事务ID。但是同时会在该条记录的信息头(recordheader)⾥⾯的deleted_flag标记位置为true,以此来表示当前记录已经被删除。所以如果经过版本⽐对
后发现找到的版本上的deleted_flag标记位为true的话,那么也不会返回,⽽是继续寻找下⼀个。

另外,如果当前事务执⾏rollback回滚的话,会把版本链中属于该事务的所有版本都删除掉

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

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

相关文章

【Spring Boot】SpringBoot 2.6.6 集成 SpringDoc 1.6.9 生成swagger接口文档

文章目录 前言一、SpringDoc是什么&#xff1f;二、使用步骤1.引入库2.配置类3.访问测试 总结其他配置立个Flag 前言 之前常用的SpringFox在2020年停止更新了&#xff0c;新项目集成SpringFox出来一堆问题&#xff0c;所以打算使用更活跃的SpringDoc&#xff0c;这里简单介绍一…

【双向传输ConvLSTM网络:Pan-Sharpening】

D2TNet: A ConvLSTM Network With Dual-Direction Transfer for Pan-Sharpening (D2TNet:用于泛锐化的双向传输ConvLSTM网络) 在本文中&#xff0c;我们提出了一种有效的卷积长短期记忆(ConvLSTM)网络&#xff0c;具有双向传输的泛锐化&#xff0c;称为D2TNet。我们设计了一个…

【ARM CoreLink 系列 3 -- CCI-550 控制器介绍 】

文章目录 CCI FamilyCCI-550 简介CCI-550 功能CCI-550 Interfaces Snoop filter 使用背景CCI-550 Snoop filter 上篇文章&#xff1a;ARM CoreLink 系列 2 – CCI-400 控制器简介 CCI Family CCI-550 简介 Arm CoreLink CCI-550 Cache Coherent Interconnect 扩展了 CoreLink…

sentinel加密狗使用及规则配置

Sentinel加密狗是一种硬件加密设备&#xff0c;用于保护软件应用程序免受未经授权的访问和复制。它可以提供软件许可管理、访问控制和数据保护等功能。下面是Sentinel加密狗的使用及规则配置的相关介绍。 Sentinel加密狗的使用 插入加密狗&#xff1a;将Sentinel加密狗插入计算…

用滑动条做调色板---cv2.getTrackbarPos(),cv2.creatTrackbar()

滑动轨迹栏作调色板 cv.createTrackbar(‘R’, ‘image’, 0, 255, nothing) 参数&#xff1a;哪个滑动轨迹栏&#xff0c;哪个窗口&#xff0c;最小值&#xff0c;最大值&#xff0c;回调函数 cv.getTrackbarPos(‘R’, ‘image’) 参数&#xff1a;轨迹栏名&#xff0c;窗口…

IMAU鸿蒙北向开发-2023年9月5日学习日志

1. 5种调试方式 1.1 Previewer 在侧边 Previewer 选项卡内可以预览Entry。 如果要单独预览组件&#xff0c;可以在给组件加Preview 装饰器 1.2 Local Emulator&#xff08;本地模拟&#xff09; 1.3 Remote Emulator&#xff08;远程模拟&#xff09; 使用时需要登录华为开发…

FSK解调技术的FPGA实现

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 一、FSK信号的解调原理 FSK信号的解调也有非相干和相干两种&#xff0c;FSK信号可以看作是用两个频率源交替传输得到的&#xff0c;所以FSK的接收机由…

[构建 Vue 组件库] 小尾巴 UI 组件库 —— 横向商品卡片(仿淘宝)

文章归档于&#xff1a;https://www.yuque.com/u27599042/row3c6 组件库地址 npm&#xff1a;https://www.npmjs.com/package/xwb-ui?activeTabreadmegitee&#xff1a;https://gitee.com/tongchaowei/xwb-ui 下载 npm i xwb-ui配置 按需导入 import {组件名 } from xwb-…

css中flex和flex-grow的区别

设置了1个class为parent且宽度为700px的div父级元素&#xff1b; 它有3个子元素&#xff0c;分别宽高为100px&#xff1b; 其中item2的元素flex值为1&#xff0c;item3的元素flex值为2 <!DOCTYPE html> <html lang"en"> <head><style>.pare…

车船边缘网关是如何给车辆船只定位的?

随着智能交通系统的不断发展&#xff0c;车路协同成为了重要的研究方向之一。而AI边缘计算网关在这个领域中发挥着至关重要的作用。本文将重点介绍AI边缘计算网关在车路协同中的应用&#xff0c;并强调其中的重点词汇或短语。 首先&#xff0c;什么是AI边缘计算网关&#xff1…

华为数据管理——《华为数据之道》

数据分析与开发 元数据是描述数据的数据&#xff0c;用于打破业务和IT之间的语言障碍&#xff0c;帮助业务更好地理解数据。 元数据是数据中台的重要的基础设施&#xff0c;元数据治理贯彻数据产生、加工、消费的全过程&#xff0c;沉淀了数据资产&#xff0c;搭建了技术和业务…

Python实现猎人猎物优化算法(HPO)优化卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

ps显示msvcp140.dll丢失的解决方法,四个解决方法分享

我想和大家分享一个关于ps显示msvcp140.dll丢失的问题以及解决方法。这个问题可能会困扰很多使用Photoshop软件的朋友&#xff0c;特别是在运行某些特定功能时&#xff0c;会出现“无法运行此程序&#xff0c;因为找不到”的错误提示。那么&#xff0c;如何解决这个问题呢&…

现在嵌入式行业工作起薪是多少呢?发展怎么样?

今天闲逛看到有位毕业大学生询问的问题&#xff0c;我就来客观讨论一下&#xff0c;其实工作方面都是起薪多少取决于你个人的学历&#xff0c;能力等背景。嵌入式岗位的就业比起其他很多工程师岗位算还不错的&#xff0c;但是不如互联网&#xff0c;这一点不用质疑。起薪多少这…

element-plus中更改分页器的文字

实现&#xff1a; main.ts 文件中增加如下代码&#xff1a; import zhCn from element-plus/es/locale/lang/zh-cn // 自定义文字&#xff08;使用默认文字不用设置&#xff09; zhCn.el.pagination.goto 跳转到 zhCn.el.pagination.pageClassifier 页 // 创建应用实例对象 c…

学校宿舍智能水电表管理系统:为节约资源保驾护航

随着科技的不断发展&#xff0c;越来越多的学校开始重视宿舍管理的智能化。其中&#xff0c;智能水电表管理系统作为一项重要的基础设施&#xff0c;已经逐渐被各大高校引入。本文将围绕学校宿舍智能水电表管理系统展开详细介绍&#xff0c;让我们一起来了解一下这个节约资源、…

[machineLearning]非监督学习unsupervised learning

1.什么是非监督学习 常见的神经网络是一种监督学习,监督学习的主要特征即为根据输入来对输出进行预测,最终会得到一个输出数值.而非监督学习的目的不在于输出,而是在于对读入的数据进行归类,选取特征,打标签,通过对于数据结构的分析来完成这些操作, 很少有最后的输出操作. 从…

搭建STM32F407的SPI-Flash(基于STM32CubeMX)

网上有不少例子&#xff0c;都对&#xff0c;但对我来说碰到几个坑&#xff0c;避免以后再犯错&#xff0c;mark下。 目标&#xff1a;通过SPI接口&#xff0c;对Nor Flash进行读写 开发板上Nor Flash 是W25Q128&#xff0c; 128Mbit&#xff0c;也就是16MB样子 CubeMx端配置…

WebClient vs HttpClient:异同对比

在 Java 开发中&#xff0c;进行网络通信是常见的需求。WebClient 和 HttpClient 是两种常用的用于发送 HTTP 请求的工具。它们都具有相似的功能&#xff0c;但在实现细节和用法上存在一些差异。本文将详细介绍 WebClient 和 HttpClient 的异同&#xff0c;帮助您选择适合您项目…

leetcode 205. 同构字符串

2023.9.6 本题维护两个映射表map&#xff0c;若发现无法对应则返回false。 代码如下&#xff1a; class Solution { public:bool isIsomorphic(string s, string t) {unordered_map<char,char> m1;unordered_map<char,char> m2;for(int i0; i<s.size(); i){//相…