MySQL:锁机制

目录

  • 概述
  • 三种层级的锁
  • 锁相关的 SQL
  • MyISAM引擎下的锁
  • InnoDB引擎下的锁
    • InnoDB下的表锁和行锁
    • InnoDB下的共享锁和排他锁
    • InnoDB下的意向锁
    • InnoDB下的记录锁,间隙锁,临键锁
      • 记录锁(Record Locks)
      • 间隙锁(Gap Locks)
      • 临键锁(Next-Key Locks)
    • InnoDB下的插入意向锁

概述

数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。

MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。

总体锁的知识分类架构如下:

在这里插入图片描述

三种层级的锁

  1. 表级锁定

表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。

当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并发度大打折扣。

  1. 页级锁定

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁。

  1. 页级锁定

行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大

从上到下,锁的粒度逐渐细粒化, 但实现开销逐渐增大。 同时我们也要须知,表锁,页锁,行锁并不是一个具体的锁,仅代表将数据库某个层级上的数据进行锁定。具体怎么去锁这个数据,还要看具体的锁实现是什么

在这里插入图片描述

锁相关的 SQL

要认识事务,SQL,与锁的知识,最好的办法就是调试。所以我这里提供给大家MySQL 8.0以及MySQL 8.0以下的查询事务持有锁情况的SQL

MySQL 8.0 以下

  1. 在TRANSACTION位置可以看到事务持有锁的情况,但是需要经验分析,名词比较难懂
show engine innodb status;
  1. 查看innodb引擎下,所有表所有事务的加锁情况,无法分别gap,record,next-key锁的具体类型。没有冲突情况无法显示持有的锁
select * from information_schema.innodb_locks`; 
  1. 查看innodb引擎下,所有表所有事务因锁的阻塞情况,谁被谁block住了
select * from information_schema.innodb_locks_wait;

MySQL 8.0

  1. 在TRANSACTION位置可以看到事务持有锁的情况,但是需要经验分析,名词比较难懂
show engine innodb status;
  1. 查看数据库中所有表所有事务的加锁情况

没有冲突,也看到持有了什么锁,具有具体的分类,简单好用,更容易分析

select * from performance_schema.data_locks`;  
  1. 查看数据库中,所有表所有事务因锁的阻塞情况,谁被谁block住了
select * from performance_schema.data_locks_wait;

MyISAM引擎下的锁

MyISAM只支持表锁,不支持行锁和页面锁。

表锁并不是一个真正的锁,只是代表对数据库表层级的数据进行锁定。具体以什么形式锁定,则要看具体的具体锁实现。

MyISAM表锁的具体实现有表级共享锁和表级排他锁。

  • 表共享读锁(表级共享锁)

获得表共享读锁的事务可以读取该表的任意数据。MyISAM引擎在执行select语句前,会自动给涉及的表加表共享读锁

  • 表独占写锁(表级排他锁)

获得表独占写锁的事务可以更新或删除该表中任意数据。在执行update,delete,insert等语句前,会自动给涉及的表加表独占写锁

很多多场合更喜欢把表级共享锁表级排他锁叫做表共享读锁表独占写锁,实际上它们的意思是一样的。

表共享读锁和表独占写锁的兼容性

在这里插入图片描述

即MyISAM的表锁可以做到,读读共享,读写互斥,写写互斥的功能

  • 读读共享: 事务A获得表读锁,事务B依然可以获得表读锁
  • 读写互斥: 事务A获得表读锁,事务B申请该表写锁则会阻塞,因为事务A获得了该表读锁,有互斥性
  • 写写互斥: 事务A获得表写锁,事务B申请该表写锁则会阻塞,因为事务A获得了该表写锁,也有互斥性

MyISAM在一定程度上还是可以支持并发的进行查询和插入操作的。即如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个线程读表的同时,另一个线程从表尾插入记录。这属于MyISAM的特性,所以InnoDB存储引擎是不支持的!

总结

  • 虽然MySQL支持表,页,行三级锁定,但MyISAM存储引擎只支持表级的数据锁定,即表锁。所以MyISAM的加锁相对比较开销低,但数据操作的并发性能相对就不高。但如果写操作都是尾插入,那么还是可以支持一定程度的读写并发
  • MyISAM的数据操作如果导致加锁行为,那么该锁肯定是一个表锁,会对全表数据进行加锁。但也要看具体什么形式的表锁,不同形式的表锁有着不同的特性
  • 从MyISAM所支持的锁中也可以看出,MyISAM是一个支持读读并发,但不支持通用读写并发,写写并发的数据库引擎,所以它更适合用于读多写少的应用场合

InnoDB引擎下的锁

InnoDB功能则更为强大,锁也更为复杂,主要以下几种:

  • 共享锁和排他锁 (Shared and Exclusive Locks)

  • 意向锁(Intention Locks)

  • 记录锁(Record Locks)

  • 间隙锁(Gap Locks)

  • 临键锁 (Next-Key Locks)

  • 插入意向锁(Insert Intention Locks)

  • 主键自增锁 (AUTO-INC Locks)

  • 空间索引断言锁(Predicate Locks for Spatial Indexes)

这里只讲重点,不讲主键自增锁,空间索引断言锁。

InnoDB下的表锁和行锁

表锁,行锁并不是一个真正的锁,只是代表可以对数据库对应层级的数据进行锁定。具体以什么形式去锁定,则要看具体的具体锁实现。

表锁具体的锁实现则有共享锁,排他锁,意向锁等。而行锁则有共享锁和排他锁,另外行锁本身还有记录锁,间隙锁和临键锁的不同算法实现。

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。 InnoDB这种行锁的实现也意味着,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,还是会出现锁冲突的,因为他们使用的是同一把锁。

当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁。但是使用不同索引查询相同行会有锁冲突。

InnoDB下的共享锁和排他锁

  • 共享锁(Shared Lock),既S锁,又称读锁。事务拿到某一行记录的S锁,才可以读取这一行的数据。共享锁可以实现读读共享,读写互斥

  • 排他锁(Exclusive Lock),既X锁,又称写锁,独占锁。事务拿到某一行记录的X锁,才可以修改或者删除这一行的数据。排他锁可以实现读写互斥,写写互斥。

因为InnoDB支持表锁和行锁。所以在数据库层次结构的表级和行级,都可以对数据进行锁定。

  • 表级共享锁:又称为表共享读锁,即在表的层级上对数据加以共享锁,实现读读共享
  • 表级排他锁:又称为表独占写锁,即在表的层级上对数据加以排他锁,实现读写互斥,写写互斥
  • 行级共享锁:即在行的层级上,对数据加以共享锁,实现对该行数据的读读共享
  • 行级排他锁:即在行的层级上,对数据加以排他锁,实现对该行数据的读写互斥,写写互斥

共享锁和排它锁的兼容性

标题共享锁排他锁
共享锁兼容不兼容
排他锁不兼容不兼容

多个事务可以拿到一把S锁,可以实现读读共享;而只有一个事务可以拿到X锁,可以实现读写互斥,写写互斥。

一句话,就是读读共享,读写互斥,写写互斥

怎么显式地加共享锁或排他锁?

  • select * from table lock in share mode 。为table的所有数据加上共享锁,既表级共享锁
  • select * from table for update。 为table的所有数据加上排他锁,既表级排他锁
  • select * from table where id = 1 for update。 为table中id为1的那行数据加上排他锁,既行级排他锁
  • select * from table where id = 1 lock in share mode。为table中id为1的那行数据加上共享锁,既行级共享锁

当然以上,加的是行锁的前提是,id为主键且在查询命中,否则行锁会轮为表锁。

InnoDB下的意向锁

通常情况下,表锁和行锁是相互冲突的,获得了表锁,就无法再获得该表具体行的行锁,反之亦然。但是有的时候表锁和行锁实现部分的共存有利于更细粒度的对锁进行控制,以便得到更加的并发性能。

例如,

事务 A 获取了某一行的排他锁,并未提交:

SELECT * FROM users WHERE id = 6 FOR UPDATE;

事务 B 想要获取 users 表的表锁:

LOCK TABLES users READ;

因为共享锁与排他锁互斥,所以事务 B 在视图对 users 表加共享锁的时候,必须保证:

  • 当前没有其他事务持有 users 表的排他锁。
  • 当前没有其他事务持有 users 表中任意一行的排他锁 。

为了检测是否满足第二个条件,事务 B 必须在确保 users 表不存在任何排他锁的前提下,去检测表中的每一行是否存在排他锁。很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了:事务 B 只要看表上有没有意向共享锁,有则说明表中有些行被共享行锁锁住了,因此,事务 B 申请表的写锁会被阻塞。这样是不是就高效多了。

所以InnoDB为了实现行锁和表锁共存的多粒度锁机制特性,InnoDB存储引擎也就还支持一种额外的锁方式以对多粒度锁机制进行支持,称之为意向锁(Intention Lock)

意向锁的维护是由存储引擎隐式帮我们做了,意向锁是由存储引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在的表的对应意向锁。

怎么理解意向锁?

  • 意向锁(Intention Lock)就是一种不与行级锁冲突的表级锁(重点!!)
  • 意向锁的主要目的展示出某事务已对表中某行加锁,或即将对表中某行加锁
  • 意向锁就是指,未来的某个时刻,事务可能要对某行加共享锁或排它锁了,先提前声明一个意向

并且意向锁具体实现又可以分为以下两种:

  • 意向共享锁(intention shared lock,IS):事务打算给表中的某些行加行级共享锁,事务在给某些行加S锁前必须先取得该表的IS锁。
  • 意向排他锁(intention exclusive lock,IX):事务打算给表中的某些加行级排他锁,事务在给某些行加X锁前必须先取得该表的IX锁。

总之所谓意向锁,就是提前表明了一个要加行锁的“意向”。当某表存在排他意向锁时,代表该表的某行可能存在行级排他锁。同理当某表存在共享意向锁时,代表该表的某行可能存在行级共享锁

意向锁的兼容性

标题意向共享锁(IS)意向排他锁(IX)表级共享锁(S)表级排他锁(X)
意向共享锁(IS)兼容兼容兼容不兼容
意向排他锁(IX)兼容兼容不兼容不兼容
表级共享锁(S)兼容不兼容兼容不兼容
表级排他锁(x)不兼容不兼容不兼容不兼容

意向锁与意向锁之间永远是兼容的,因为当你不论加行级的 X 锁或 S 锁,都会自动获取表级的 IX 锁或者 IS 锁。也就是你有 10 个事务,对不同的 10 行加了行级 X 锁,那么这个时候就存在 10 个 IX 锁。

这 10 个 IX 存在的作用是啥呢,就是假如这个时候有个事务,想对整个表加排它 X 锁,那它不需要遍历每一行是否存在 S 或 X 锁,而是看有没有存在 意向锁,只要存在一个意向锁,那这个事务就加不了表级排它(X)锁,要等上面 10 个 IX 全部释放才行。

意向锁还有一个好处

(1)事务A向student表申请某个行记录的S锁(行级),所以首先要为student表上IS锁。
(2)事务A获得锁完毕后,事务B向student表申请全表的S锁(表级)。于是数据库开始锁冲突的判定
(3)数据库首先判断事务B申请表锁前,student表是否已经存在表级S,X锁,发现没有
(4)数据库再判断student是否已经存在意向锁IS,IX,然后发生之前有事务A申请过IS锁
(5)根据表级S锁和意向IS锁的兼容性策略,两者是兼容的。所以事务B直接就获得对student表的表级S锁
(6)此时student表已经共存了表级S锁和行级S锁。

所以意向锁的出现也让表锁和行锁得到一定的共存,提供了部分的并发性能!

InnoDB下的记录锁,间隙锁,临键锁

我们的行锁根据锁的粗细粒度又可以分为三种锁,记录锁间隙锁临键锁

记录锁(Record Locks)

记录锁(Record Lock)就是我们最单纯认知的行锁,既只锁住一条行记录,准确的说是一条索引记录
InnoDB的行锁是依赖索引实现的,而其锁住某行数据的本质是锁住行数据对应在聚簇索引的索引记录。

例如某个事务执行了select * from t where id=1 for update;语句,就相当于它会在id = 1的索引记录上加上一把锁,以阻止其他事务插入,更新,删除id = 1的这一行。

  • 记录锁是锁住记录,锁住索引记录,而不是真正的数据记录。
  • 如果要锁的列没有索引,进行全表记录加锁。
  • 记录锁也是排它 (X) 锁,所以会阻塞其他事务对其插入、更新、删除。

间隙锁(Gap Locks)

间隙锁(Gap Lock),顾名思义,它会封锁索引记录中的“缝隙”,不让其他事务在“缝隙”中插入数据。 它锁定的是一个不包含索引本身的开区间范围 (index1,index2)。间隙锁是封锁索引记录之间的间隙,或者封锁第一条索引记录之前的范围,又或者最后一条索引记录之后的范围

说白了,间隙锁的目的就是为了防止索引间隔被其他事务的 “插入”。 间隙锁是InnoDB权衡性能和并发性后出来的特性。

间隙锁之间是互相兼容的,既不同事务的Gap锁是可以共存的,可以存在重合区域或是完全重合。多个事务的Gap锁重合代表多个事务都想阻止其他事务往该索引间隙 “插入” 数据。也因为Gap一次就对插入行为锁住了一片的区域,不利于多事务并发写。所以后续MySQL也就提供了一种特殊的间隙锁(插入意向锁),以解决并发写的问题

间隙锁实际也分共享间隙锁,排他间隙锁,虽然有分类,但事实上他们的意义是等价毫无区别的,所以可以忽略这一层,只要知道它们的作用都是阻止其他事务往间隙插入数据。

间隙锁只发生在事务隔离级别为RR(Repeatable Read)的情况下,它用于在隔离级别为RR时,阻止幻读(phantom row)的发生;隔离级别为RC时,搜索和索引扫描时,Gap锁是被禁用的,只在外键约束检查和 重复key检查时Gap锁才有效,正是因为此,RC时会幻读问题。

比如某个事务执行select * from table where id between 10 and 20 for update;语句,当其他事务往表里 “插入” id在(10,20)之间的值时,就会被(10,20)的间隙锁给阻塞。

临键锁(Next-Key Locks)

Next-key 锁是记录锁和间隙锁的组合,它指的是加在 某条记录以及这条记录前面间隙上 的锁。

也可以理解为一种特殊的间隙锁。通过临建锁可以解决幻读的问题。每个数据行上的非唯一索引列(该索引里面的值允许重复)上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段 左开右闭 区间的数据。

需要强调的一点是,InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁。

假设有如下表:id 主键,age 普通索引。

idnameage
1zhangsan10
3lisi24
5wangwu32
7zhaoliu45

该表中 age 列潜在的临键锁有:(-∞, 10],(10, 24],(24, 32],(32, 45],(45, +∞]。

在事务 A 中执行如下命令:

-- 根据非唯一索引列 UPDATE 某条记录 
UPDATE table SET name = Vladimir WHERE age = 24; -- 或根据非唯一索引列 锁住某条记录 
SELECT * FROM table WHERE age = 24 FOR UPDATE;

不管执行了上述 SQL 中的哪一句,之后如果在事务 B 中执行以下命令,则该命令会被阻塞:

INSERT INTO table VALUES(100, 26, 'tianqi');

很明显,事务 A 在对 age 为 24 的列进行 UPDATE 操作的同时,也获取了 (10, 32] 这个区间内的 临键锁。

这里对 记录锁、间隙锁、临键锁 做一个总结:

我们知道InnoDB的行锁默认是基于B+Tree的。所以行锁依赖的索引是有序的。

  • 记录锁就是单纯意义上的行锁,锁的就是单行数据,该数据是真实存在的
  • 而间隙锁则是锁住一个区间中多行数据,但这些多行的数据实际是并不存在的。既只锁住真实数据对应索引项之间的一个空间范围
  • 而临键锁说白了就是记录锁+间隙锁的组合。只要把记录锁和间隙锁组合在一起,就是临键锁,既锁住索引项本身的真实数据,又锁住两两索引之间没有数据的空间范围。

InnoDB下的插入意向锁

插入意向锁是在插入一条记录行前,由 INSERT 操作产生的一种特殊的间隙锁。

该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。

假设存在两条值分别为 4 和 7 的记录,两个不同的事务分别试图插入值为 5 和 6 的两条记录,每个事务在获取插入行上独占的(排他)锁前,都会获取(4,7 ] 之间的间隙锁,但是因为数据行之间并不冲突,所以两个事务之间并不会产生冲突(阻塞等待)。

总结来说,插入意向锁 的特性可以分成两部分:

插入意向锁是 一种特殊的间隙锁 —— 间隙锁可以锁定开区间内的部分记录。

  • 插入意向锁之间互不排斥,所以即使多个事务在同一区间插入多条记录,只要记录本身(主键、唯一索引)不冲突,那么事务之间就不会出现冲突等待。
  • 虽然插入意向锁中含有意向锁三个字,但是它并不属于意向锁而属于间隙锁,因为意向锁是表锁,而插入意向锁是行锁。

插入意向锁的作用?以及为何替代Gap锁

为普通的Gap锁一旦锁住了某个间隙,这个间隙就不再允许其他事务插入数据了。既其他事务需要等待当前事务释放该区间的Gap锁后,才能插入数据。所以我们可以知道,因为Gap锁对插入行为的相对锁粒度比较大,就不利于提高多事务对同一个索引间隙的数据插入性能了。

插入意向锁就不一样了,插入意向锁虽然跟Gap锁一样,一次锁的是一个区间。但是它可以允许多个事务在这个区间内执行不同数据的插入,互不干扰。

参考:
【MySQL笔记】正确的理解MySQL中让你想到就烦的各种锁

【数据库】MySQL 中的锁机制

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

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

相关文章

彻底删除Ubuntu双系统(联想小新2022)

彻底卸载Ubuntu双系统 以里联想小新pro16 i9-12900h为例子 把开机启动项设为默认Windows启动 以联想电脑为例子,关机后一直点击Fn F2进入Bios把windows启动项移到最上面,这样可以开机默认启动windows了删除ubuntu系统分区 使用磁盘管理软件 DiskGeniu…

【手把手教你】将python程序打包成exe可执行文件

1. 安装环境 pip install pyinstaller6.0.02. 打包文件 pyinstaller -D “要启动的文件名“.py比如我的命令就是:pyinstaller -D eval.py 执行完后,会生两个文件夹dist和bulib两个文件和一个xxx.spec文件 3. 删除生成的文件 删除生成的bulid和dist文…

19、Flink 的Table API 和 SQL 中的内置函数及示例(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

JAVA 版小程序商城免费搭建 多商家入驻 直播带货 商城系统 B2B2C 商城源码之 B2B2C产品概述

1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

4.移位计算,乘除法运算

目录 一. 移位计算 (1)算数移位 (2)逻辑移位 (3)循环移位 二. 乘法运算 (1)原码的乘法运算 (2)补码的乘法运算 三. 除法运算 (1&#xf…

MySQL -- mysql connect

MySQL – mysql connect 文章目录 MySQL -- mysql connect一、Connector/C 使用1.环境安装2.尝试链接mysql client 二、MySQL接口1.初始化2.链接数据库3.下发mysql命令4.获取执行结果5.关闭mysql链接6.在C语言中连接MySQL 三、MySQL图形化界面推荐 使用C接口库来进行连接 一、…

【无代码】【VR开发】【Unity】【VRTK】4-导入VRTK Tilia Package

【导入VRTK V4】 VRTK的Tilia Package包含了一整套空间开发方案。导入后你可以在PackageManager中看到它们。 所有的Tilia包都可以在如下页面找到: https://www.vrtk.io/tilia.html Tilia包有一个安装器,可以让你仅仅安装需要的包。包的种类很多,按照适用方向分类。 点击H…

关于Web端 —— UI自动化测试

在手工测试阶段,针对项目输出了测试用例,如果这些测试用例需要在版本迭代的过程中,需要进行回归测试,通过手工重复地执行测试用例,将会耗费大量的人力。 为此应运而生就有了自动化测试,通过使用自动化工具…

行情分析——加密货币市场大盘走势(11.7)

大饼昨日下跌过后开始有回调的迹象,现在还是在做指标修复,大饼的策略保持逢低做多。稳健的依然是不碰,目前涨不上去,跌不下来。 以太昨天给的策略,依然有效,现在以太坊开始回调。 目前来看,回踩…

深度学习经典网络:GoogleNet

深度学习经典网络--GoogleNet 1、为什么要提出Inception2、为什么是Inception3、实际中的Inception4、GoogleNet 整体网络结构 GoogLeNet是google推出的基于Inception模块的深度神经网络模型,在2014年的ImageNet竞赛中夺得了冠军,在随后的两年中一直在改…

野火霸天虎 STM32F407 学习笔记_5 按键输入;位带操作介绍

输入——按键点灯 开发板按键电路如下: 按键未按下接地,按下后为高电平。电容起到消抖作用,软件处理就不需要手动延时消抖了。 编程没啥难度,就是改了一下输入模式。使用 ReadInputDataBits 读取。 //bsp_button.c #include &q…

IP可视对讲实时录制系统

介绍 软件架构 技术支持 CallRecored介绍 IP可视对讲实时录制系统设计了数据库表,并完成了数据库建模,采用了视频编解码技术,高效网络传输,磁盘高效读写技术,以及提供开放接口。 系统客户端采用扁平化UI,…

微前端qiankun嵌入vue项目后iconfont显示方块

个人项目地址: SubTopH前端开发个人站 (自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面) SubTopH前端开发个人…

点信息标注_BillboardTextActor3D

开发环境: Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example参考代码 demo解决问题:点附近创建左边或其他信息,且信息面板显示状态不受相机缩放、旋转影响 prj name: BillboardTextActor3D #include…

2022最新版-李宏毅机器学习深度学习课程-P34 自注意力机制类别总结

在课程的transformer视频中,李老师详细介绍了部分self-attention内容,但是self-attention其实还有各种各样的变化形式: 一、Self-attention运算存在的问题 在self-attention中,假设输入序列(query)长度是N…

2023 electron最新最简版windows、mac打包、自动升级详解

这里我将讲解一下从0搭建一个electron最简版架子,以及如何实现打包自动化更新 之前我有写过两篇文章关于electron框架概述以及 常用api的使用,感兴趣的同学可以看看 Electron桌面应用开发 Electron桌面应用开发2 搭建electron 官方文档:ht…

Vscode Vim自动切换

在VsCode里安装了Vim插件,由于Vim插件存在Normal和Insert两种模式,会需要经常性的按shift切换中英文,太过麻烦,本文介绍一下如何通过im-select来解决。 首先先确保自己的电脑里装有英文语言包,win10系统下可以使用Win…

【机器学习4】降维

常见的降维方法有主成分分析、 线性判别分析、 等距映射、 局部线性嵌入、 拉普拉斯特征映射、 局部保留投影等。 1 PCA最大方差角度理解 PCA无监督学习算法。 PCA的目标, 即最大化投影方差, 也就是让数据在主轴上投影的方差最大。 在黄线所处的轴上&…

Windows环境下编译OLLVM源码(VS2022)

windows环境下编译OLLVM 13.x VisualStudio配置下载OLLVM13.xollvm的使用 网上关于windows环境编译ollvm信息比较杂乱,在此编译成功的基础上做一下总结! VisualStudio配置 1,正常配置C桌面环境 2,在单个组件中选择用于Windows得C…

【算法与数据结构】77、LeetCode组合

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:如果k是固定的,最直接的方法就是建立k个for循环,将结果全部压入result容器中。…