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

MySQL——插入加锁/唯一索引插入死锁/批量插入效率

本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致的死锁情况,以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法;

MySQL跟加锁相关的一些概念

在介绍MySQL执行插入的加锁过程之前,先复习下几种跟锁相关的概念;

快照读

  • InnoDB 利用了“所有数据都有多个版本”的这个特性,实现了“秒级创建快照”的能力;

  • 快照是整库级别;

  • 数据版本与事务ID一一对应;

  • 各个数据版本通过当前数据与期间的undo log作用得到;

  • 判断数据是否可见的规则——对于当前事务,如果一个数据版本是在其启动之前生成的,就认;如果是我启动以后才生成的,就不认,我必须要找到它的上一个版本;如果是这个事务自己更新的数据,它自己还是要认的;

  • 一致性视图生成的时机(即视图数组确定的时机)并非事务的begin命令,而是事务内的第一个select语句;trx_id生成的时机是事务开启后的第一个当前读DML语句;因此,可能存在"trx_id小于当前事务A,但未提交的事务A_pre"和"trx_id大于当前事务A,但未提交的事务A_behind";

  • 对于innoDB默认的可重复读级别下,查询只承认在一致性视图创建前就已经提交完成的数据;对于读提交,查询只承认在语句执行前就已经提交完成的数据;

  • 不管哪个事务隔离级别,写操作都是当前读;当前读,总是读取已经提交完成的最新版本;

当前读

  • 新数据都是先读后写的,而这个读,只能读当前最新的值,称为“当前读”(currentread);

  • 行锁是在事务执行更新语句时加上的,要等到事务结束时才释放;

  • 除了update 之类的写操作语句外,select语句也可以加行锁,也是当前读; select ... lock in share mode 对数据行加读锁(S锁,共享锁), select ... for update对数据行加写锁(X锁,排他锁);

S锁

  • S锁,英文为Shared Lock,共享锁,也称之为读锁,即Read Lock;

  • S锁之间是共享的,或者说是互不阻塞的;

  • 执行select ... lock in share mode读取一条记录时,需要先获取该记录的S锁;

  • S锁规则——事务T1对记录R1加上了S锁,那么当前事务T1可以读取R1这一行记录,但是不能修改R1,其他事务T2可以继续对R1添加S锁,但是不能添加X锁,只有当R1上面的S锁释放了,才能加上X锁;

X锁

  • X锁,英文为Exclusive Lock,排他锁,也称之为写锁,即Write Lock;如同它的名字,X锁是具有排他性的,即一个写锁会阻塞其他的X锁和S锁

  • 当事务需要修改一条记录时(或执行 select ... for update),需要先获取该记录的X锁;

  • 当然,更新数据之前肯定是需要读到最新数据的,因此获取X锁不影响当前事务读取最新数据

幻读

  • 事务执行更新的期间,若允许插入了新的数据,导致事更新到了新插入的数据,相当于发生了幻读——事务前后看到的数据不一样,当前读读到了"多出来的"一些数据;

  • 幻读破坏了加锁的语义——满足更新语句条件的记录在事务中途增加了,没锁住;

  • 此外,幻读影响了binlog与主库数据的一致性——binlog在事务commit时生成,若事务A先执行更新,同时事务B执行插入后commit,然后A再提交,则会导致从库执行binlog时更新到了"预期之外"的行,导致主从数据不一致

间隙锁gap lock

  • gap lock锁的是插入行为;gap lock锁之间其实并不互斥;

  • 为了解决幻读问题,InnoDB引入间隙锁 (Gap Lock),锁的就是两个值之间的空隙,可以是主键,也可以是二级索引;

next-key lock

为解决幻读问题引入了间隙锁,再加上更新数据时的行锁,合在一起称为next-key lock;把间隙锁记为开区间,因此每个next-key lock是前开后闭区间;

间隙锁和next-key lock的引入,解决了幻读的问题,但同时在并发情况下,可能导致死锁发生,原因是间隙锁获取不冲突导致多个线程都持有同一个间隙锁,但是执行插入时会冲突;

插入意向锁

插入意向锁准确的说它不是锁,而是插入行为;插入意向锁与间隙锁gap lock冲突;配合上面的间隙锁gap lock一起防止了幻读;

如果插入的记录有唯一索引,还会进行Duplicate Key判断,因此需要当前读;如果存在相同Key且该Key被加了互斥锁,则会加S锁(共享锁),然后等待(因为这个相同的Key之后有可能会回滚删除,这里非常容易死锁),直到等到成功插入后,会在这条记录上加X锁(排他锁);最后在当前事务提交/回滚时释放X锁;

MySQL执行插入Insert时的加锁过程

MySQL官方文档对Insert加锁情况的描述

INSERT sets an exclusive lock on the inserted row. This lock is an index-record lock, not a next-key lock (that is, there is no gap lock) and does not prevent other sessions from inserting into the gap before the inserted row.

Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap. Suppose that there are index records with values of 4 and 7. Separate transactions that attempt to insert values of 5 and 6 each lock the gap between 4 and 7 with insert intention locks prior to obtaining the exclusive lock on the inserted row, but do not block each other because the rows are nonconflicting.

If a duplicate-key error occurs, a shared lock on the duplicate index record is set. This use of a shared lock can result in deadlock should there be multiple sessions trying to insert the same row if another session already has an exclusive lock. This can occur if another session deletes the row.

解读:

1. INSERT操作会对新插入的记录加行锁写锁(排它锁X锁);注意:区别于执行update,执行insert时这里加的是X锁,并非next-key lock,因此不会阻塞其他的事务对gap区间的插入操作;

2. 在插入记录前,会向插入记录所在位置申请意向插入意向锁(Insertion Intention Gap Lock);只要不是插入的是同一行记录,多个事务对相同gap区间的插入操作不会冲突;

3. 对于唯一索引,发生唯一键冲突时,当前事务会先尝试在这条记录上加读锁S锁;加S锁的机制可能会导致死锁:即A线程占用记录的X锁,B、C阻塞,它们需要先获取S锁再获取X锁执行更新;当A释放X锁时,B、C同时拿到S锁(共享锁),但互相都无法继续获取X锁(S锁与X锁互斥),导致死锁;

下面通过几个case来验证和说明上面的insert的加锁过程,简化的表结构如下:

CREATE TABLE `t1` (`id` int(11) NOT NULL AUTO_INCREMENT,`a` varchar(5),`b` varchar(5),PRIMARY KEY (`id`),UNIQUE KEY `uk_name` (`a`,`b`)
);

case1:并发事务先后插入同一行

在记录不存在的情况下,两个同样顺序的批量insert同时执行,第二个会进行锁等待状态;现象如下:

解释:

  • insert加的是插入意向锁,它是隐式锁;隐式锁的意思就是没有锁,但是可能因为一些触发规则被升级成行锁;

  • 在t1插入记录时,是不加锁的;这个时候事务t1还未提交的情况下,事务t2尝试插入的时候,发现有这条记录;根据官方文档描述,t2会尝试获取S锁,它会判定记录上的事务id是否活跃(存在正在执行还未提交的事务),如果活跃的话,说明正在修改记录的事务未结束,会帮t1把它的隐式锁提升为显式锁(X锁);因此,t1持有X锁,而t2尝试获得S锁,X锁与S锁冲突,t2阻塞

case2:批量插入顺序不一致的导致的死锁

根据case1的结论,当多个事务线程批量插入数据的插入顺序不一致时,会导致死锁;现象及解释如下:

解决方法:在业务侧对插入的数据做好排序,保证并发执行时不会产生死锁;

case3:delete提交但未purge导致的并发insert死锁

关于purge的相关知识,可参考我的MySQL——关于删除/purge/删除加锁/删除大量数据/truncate&delete这篇文章;

begin;
delete from t1 where a = '25'
commit;begin;
INSERT ignore INTO `t1` (`a`, `b`) VALUES('25','1')
commit;

这块代码在多个线程同时调用的时候,非常容易死锁;注意这块代码里面有2个事务

解释:

  • 执行delete事务提交成功,若还没来得及 purge(被执行purge的对象包括UNIQUE KEY(a,b)),这时后面的事务执行这条记录的insert时会先尝试对这条记录加S锁;

  • 并发情况下,多个insert事务获取S锁成功,但是在执行(含唯一索引)insert时,需要获取X锁,此时并发的线程会出现——同时拿到S锁(共享锁),但互相都无法继续获取X锁(S锁与X锁互斥),导致死锁;

case4:3个 insert ignore,一个回滚造成的死锁

这个case就跟官方文档中表述的一致——

"If a duplicate-key error occurs, a shared lock on the duplicate index record is set. This use of a shared lock can result in deadlock should there be multiple sessions trying to insert the same row if another session already has an exclusive lock."

当互斥锁释放时,并发的insert线程会由于先尝试获取的S锁,而导致后序获取X锁时产生死锁;

实验如下:本地MySQL 5.7版本开3个链接窗口,关闭自动提交,按照如下顺序操作,结果如预期一样出现死锁;

通过 SHOW ENGINE INNODB STATUS; 命令,查看日志如下:

=====================================
2023-03-08 15:15:13 0x7fa4 INNODB MONITOR OUTPUT
=====================================
略
------------------------
LATEST DETECTED DEADLOCK ## 最新的死锁
------------------------
2023-03-08 15:10:12 0x7fa4 ## 这里显示了最近一次发生死锁的日期和时间
*** (1) TRANSACTION: ## 事务1
TRANSACTION 220709, ACTIVE 10 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 16, OS thread handle 25992, query id 158597 localhost 127.0.0.1 root update
INSERT ignore INTO `user` (`id`,`username`, `age`, `birthday`, `sex`, `address`, `update_time`) VALUES (55,'小明', 5, '2019-09-17 19:12:37', '男', '杭州', '2022-09-01 16:03:25')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:  
## 解释:事务1在等X锁(主键索引space id 302 page no 3 n bits 88 index PRIMARY)
RECORD LOCKS space id 302 page no 3 n bits 88 index PRIMARY of table `mybatis_01`.`user` trx id 220709 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 19 PHYSICAL RECORD: n_fields 9; compact format; info bits 0
略*** (2) TRANSACTION: ## 事务1
TRANSACTION 220708, ACTIVE 25 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 7, OS thread handle 32676, query id 158584 localhost 127.0.0.1 root update
INSERT ignore INTO `user` (`id`,`username`, `age`, `birthday`, `sex`, `address`, `update_time`) VALUES (55,'小明', 5, '2019-09-17 19:12:37', '男', '杭州', '2022-09-01 16:03:25')
*** (2) HOLDS THE LOCK(S): 
## 解释:事务2持有S锁(主键索引space id 302 page no 3 n bits 88 index PRIMARY,跟上面事务1等的X锁为同一行,X锁与S锁互斥,因此事务1得等事务2释放行锁)
RECORD LOCKS space id 302 page no 3 n bits 88 index PRIMARY of table `mybatis_01`.`user` trx id 220708 lock mode S locks gap before rec
Record lock, heap no 19 PHYSICAL RECORD: n_fields 9; compact format; info bits 0
略*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
## 解释:事务2在等X锁(主键索引space id 302 page no 3 n bits 88 index PRIMARY,跟上面事务1等的X锁为同一把锁,而事务1在等事务2持有的S锁释放,因此死锁)
RECORD LOCKS space id 302 page no 3 n bits 88 index PRIMARY of table `mybatis_01`.`user` trx id 220708 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 19 PHYSICAL RECORD: n_fields 9; compact format; info bits 0
略*** WE ROLL BACK TRANSACTION (2)
## 解释:根据事务回滚成本,选择事务2回滚,释放S锁
------------

死锁日志的查看方法可参考:MySQL死锁日志、MySQL死锁日志的查看和分析

MySQL insert加锁流程(重要)

1. 首先对插入的间隙加插入意向锁(Insert Intension Locks);注意插入意向锁可以理解为只是个插入动作,并非真的加锁,它只跟GAP锁(间隙锁)锁的插入区间冲突;

  • 如果该间隙已被加上了GAP锁(间隙锁)或 Next-Key 锁(含GAP 锁),则加锁失败,等待间隙释放;

  • 如果没有,则加插入意向锁成功,表示可以插入;

2. [可选 唯一键]然后判断插入记录是否有唯一键,如果有,则需要进行唯一性约束检查:

  • 如果不存在相同键值,则准备插入;

  • 如果存在相同键值,则判断该键值是否加锁;

  • 如果没有锁, 判断该记录是否被标记为删除;

  • 如果标记为删除,说明删除事务已经提交,数据页上的记录还没来得及 purge,这时尝试加S锁;

  • 如果没有标记删除,说明数据已存在,本次插入会导致唯一键冲突,则报 1062 duplicate key 错误;

  • 如果有锁,说明该记录正在被处理(正在被其他事务新增、删除或更新),且其他事务还未提交,则当前事务尝试加S锁后会进入阻塞,等待其他事务释放记录X锁;

3. 插入记录并对记录加X锁,当前事务提交或回滚时释放X锁;

insert加锁的小结

  1. 关于隐式锁,一般使用自增主键且不含唯一键的insert语句,并发时不会有冲突,因为插入意向锁是隐式锁,实际代表的是一个准备插入的行为;这个行为只和间隙锁GAP锁冲突;

  1. 关于锁升级,当插入的数据含唯一键,出现并发插入时(如事务A和事务B,事务A先执行insert但还未提交事务),后执行插入的事务B会使用当前读,如果发现这条记录已存在(还未提交),则会先尝试获取S锁;此时事务A的插入意向锁(隐式锁)会被提升为显式锁( X 锁),导致事务B阻塞;

  1. 关于插入死锁;正是MySQL这种唯一键冲突时的insert插入获取锁的规则,导致了在[case2: 并发插入事务中的顺序顺序不一致]、[case3: 删除提交但还未purge]、或[case4: 并发插入事务中单条回滚]的case下,会出现并行的事务先拿到S锁(共享锁),但在执行insert加X锁时,发现阻塞,构成死锁;这个问题在MySQL官方文档也提到了;

建议

  • 针对case2,保证各个事务线程执行插入时,插入数据的顺序相同,避免死锁;

  • 针对case3和case4,保证各个事务线程执行含唯一键的数据插入前,先对数据加X锁,即跳过insert加锁机制的先尝试获取S锁这一阶段;如select ... for update;如果查到了,则跳过插入;

有哪些提升MySQL插入性能的方法?

今天有个同事问我,有个业务场景,需要提升MySQL插入的性能,问我有哪些思路;

我的第一反应是,大部分的互联网场景都是读多写少,很少见写入密集型的业务场景,高并发写本就不适合用MySQL;

大量的写操作会产生大量日志,消耗IO与带宽资源,同时会一定程度影响查询性能;此外,在读写分离的架构下,会导致主从延迟升高,从库难以追上主库,导致一些查询场景查到的数据一直是是"旧的",引起业务问题;

不过还是从MySQL的角度,提供了几点优化思路:

1. 使用批量插入替代逐条插入

批量插入意味着多条插入语句放入了一个事务里;而单条插入时,每条语句都会生成一条事务;

优点是通过合并批量插入语句到单个事务,可以减少创建事务的消耗;

缺点也很明显,这个事务的会随着批次bitchSize的增加,变成一个长事务,会导致较大的回滚成本以及主从延迟增加;因此需要权衡这个bitchSize的大小,建议不要超过100;

2. 修改SQL语句的写法

将事务内多条insert values语句合并起来;如下,

INSERT INTO `t` (`datetime`, `uid`, `content`, `type`) VALUES ('0', 'userid_0', 'content_0', 0);  
INSERT INTO `t` (`datetime`, `uid`, `content`, `type`) VALUES ('1', 'userid_1', 'content_1', 1); 

改为:

INSERT INTO `t` (`datetime`, `uid`, `content`, `type`) VALUES('0', 'userid_0', 'content_0', 0),('1', 'userid_1', 'content_1', 1); 

这种方法优化的效果理论上还是有的,执行SQL产生的binlog大小减少了,降低日志刷盘的数据量和频率;并且通过合并SQL语句,减小了SQL语句的传输大小,减少网络传输的IO;同时也能减少SQL语句解析的次数;

3. 尽量保证数据有序插入

如果插入的表上存在索引,可以在插入前尽量让插入的数据按索引排序,如在业务代码内做一下手动排序;如果有多个索引,则选择索引树较大的那个索引,对齐字段做排序;

在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表;每一个索引在InnoDB里面对应一棵B+树,所有叶子节点构成一个有序链表,也就是说是有序的

数据库插入时,需要维护索引数据,而无序的记录会增大维护索引的成本;

试想如果每次插入记录都在索引的最后面,索引的定位效率很高,并且对索引调整较小;

如果插入的记录在索引中间,插入记录的索引定位效率会下降;并且数据插到叶子节点时,可能引起页分裂/页合并,数据量较大时会有频繁的IO操作,会消耗比较多CPU和IO资源;

4. 修改innodb_flush_log_at_trx_commit参数

InnoDB提供了innodb_flush_log_at_trx_commit参数,来控制redolog的写入策略:

  • 设置为0,表示每次事务提交时都只是把redolog留在redolog buffer中;

  • 设置为1,表示每次事务提交时都将redolog直接持久化到磁盘;

  • 设置为2,表示每次事务提交时都只是把redolog写到page cache;

InnoDB有一个后台线程,默认每隔1秒,就会把redolog buffer中的日志,调用write写到文件系统的page cache,然后调用fsync持久化到磁盘;

为了缓解IO压力,可以让redolog的落盘不要那么频繁,完全依赖后台线程,则可以将innodb_flush_log_at_trx_commit修改为0;

缺点也很明显,但Sever断电时有丢失数据风险,会丢失这个落盘任务执行间隔之间变更的数据;一般作为业务侧,是用不到这个方法的,也是不推荐的;

这里提一下问题本身:一个处理流程中,包含一次insert和一次RPC调用,而insert的性能瓶颈成为了这个流程执行效率的瓶颈;

同事一开始的思路是优化插入操作的性能,但在我询问了这条insert与RPC是否有数据强一致性关联时,他捋了捋发现并没有;

所以解决问题的方案很简单——将insert从处理流程中去掉就行了!

是不是很简单,提前用任务插入,或者流程中异步插入,控制插入执行的速率,如通过MQ;哪怕真的有数据强一致性关联,也应该使用其他写性能很高的存储引擎,如redis;

所以解决问题的思路要视野宏观一段,切勿一叶障目;不过也借此机会,梳理了下MySQL插入相关的知识点;

本篇参考:

我的文章——幻读/间隙锁/Next-Key Lock

S锁与X锁 / 当前读与快照读

读MySQL源码再看INSERT加锁流程

MySQL插入死锁套路

MySQL 死锁套路:一次诡异的批量插入死锁问题分析

修改MySQL配置来提高mysql插入速度的方法

MySQL批量SQL插入性能优化

解决死锁之路 - 常见 SQL 语句的加锁分析

相关文章:

MySQL——插入加锁/唯一索引插入死锁/批量插入效率

本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致的死锁情况,以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法;MySQL跟加锁相关的一些概念在介绍MySQL执行插入的加锁过程之前&…...

【专项训练】数组、链表

数组array: list = []链表linked list # Definition for singly-linked list. class ListNode:def __init__(self, x):self.val = xself.next =...

基于Jeecgboot前后端分离的ERP系统开发代码生成(六)

商品信息原先生成的不符合要求,重新生成,包括一个附表商品价格信息表 一、采用TAB主题一对多的模式 因为主键,在online表单配置是灰的,所以不能进行外键管理,只能通过下面数据库进行关联录入,否则online界面…...

什么?同步代码块失效了?-- 自定义类加载器引起的问题

一、背景 最近编码过程中遇到了一个非常奇怪的问题,基于单例对象的同步代码块似乎失效了,百思不得其姐。 下面给出模拟过程和最终的结论。 二、场景描述和模拟 2.1 现象描述 Database实现单例,在 init 方法中使用同步代码块来保证 data不…...

CHAPTER 4 文件共享 - Samba

文件共享 - Samba1 Samba1.1 Samba的软件架构1.2 搭建Samba服务器1.3 samba用户管理1. 添加用户2. 修改用户密码3. 删除用户和密码4. 查看samba用户列表5. 查看samba服务器状态1.4 samba共享设置(配置文件详解)1.5 访问共享目录1. windows访问2. linux客…...

深入分析@Configuration源码

文章目录一、源码时序图1. 注册ConfigurationClassPostProcessor流程源码时序图2. 注册ConfigurationAnnotationConfig流程源码时序图3. 实例化流程源码时序图二、源码解析1. 注册ConfigurationClassPostProcessor流程源码解析(1)运行案例程序启动类Conf…...

Unity 代码优化 内存管理优化

项目遇到了卡顿的情况 仔细检查了代码没检查出有误的地方 仔细的总结了一下可以优化的东西 解决了卡顿 记录一下 1 协程 项目之前写的关于倒计时之类的东西 都是开了个协程 虽然协程是消耗很小的线程 , 可是还是有额外消耗 而且 有很多用携程来检测销毁预制体的操作 也都放到U…...

设计模式~门面(外观)模式(Facade)-08

目录 (1)优点 (2)缺点 (3)使用场景 (4)注意事项: (5)应用实例: (6)源码中的经典应用 代码 外观模式&am…...

C++面向对象编程之一:封装

C面向对象编程三大特性为:封装,继承,多态。C认为万事万物皆为对象,对象有属性和行为。比如:游戏里的地图场景可以看作是长方形对象,属性场景id,有长,有宽,可能有NPC&…...

IDEA插件系列(3):Maven Helper插件

一、引言在写Java代码的时候,我们可能会出现Jar包的冲突的问题,这时候就需要我们去解决依赖冲突了,而解决依赖冲突就需要先找到是那些依赖发生了冲突,当项目比较小的时候,还比较依靠IEDA的【Diagrams】查看依赖关系&am…...

SAP 更改物料基本计量单位

前言部分 在SAP中物料创建后,一旦发生业务,其基本计量单位便很难修改。由于单位无法满足业务要求,往往会要求新建一个物料替代旧物料。这时候除了要将旧物料上所有的未清业务删除外,还需要替换工艺与BOM中的旧物料。特别是当出现旧…...

蓝桥web基础知识学习

HTMLCSS 知识点重要指数HTML 基础标签🌟🌟🌟🌟🌟HTML5 新特性🌟🌟🌟🌟🌟HTML5 本地存储🌟🌟🌟🌟CSS 基础语法…...

Python+ChatGPT制作一个AI实用百宝箱

目录一、注册OpenAI二、搭建网站及其框架三、AI聊天机器人四、AI绘画机器人ChatGPT 最近在互联网掀起了一阵热潮,其高度智能化的功能能够给我们现实生活带来诸多的便利,可以帮助你写文章、写报告、写周报、做表格、做策划甚至还会写代码。只要与文字相关…...

Python中格式化字符串输出的4种方式

Python格式化字符串的4中方式 一、%号 二、str.format(args) 三、f-Strings 四、标准库模板 五、总结四种方式的应用场景’ 一、%号占位符 这是一种引入最早的一种,也是比较容易理解的一种方式.使用方式为: 1、格式化字符串中变化的部分使用占位符 2、…...

C#基础教程15 枚举与类

文章目录 C# 枚举(Enum)声明 enum 变量C# 类(Class)类的定义成员函数和封装C# 中的构造函数关键字 staticC# 枚举(Enum) 枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。 C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。 声明 enum 变…...

三步 让你的 vscode 自动编译ts文件

三步让你的 vscode 自动编译ts文件 TypeScript环境安装与如何在vscode实现自动编译ts文件? 文章目录三步让你的 vscode 自动编译ts文件前提条件环境安装自动编译运行监视任务时报错?前提条件 安装 node 环境 环境安装 tsc 作用:负责将ts 代码 转为 浏…...

STM32程序下载和启动方式

目录1 BOOT引脚配置和下载说明2 关于串口下载方式3 关于一按复位就跑代码4 关于下载调试速度5 关于三种启动方式5.1 FLASH启动5.2 系统存储器器启动5.3 SRAM启动6 关于程序的三种下载方式1 BOOT引脚配置和下载说明 BOOT0BOOT1程序运行ST-Link下载串口下载启动说明xx无0x√√用…...

基础01-ajax fetch axios 的区别

ajax fetch axios 的区别 题目 ajax fetch axios 的区别 分析 三者根本没有可比性,不要被题目搞混了。要说出他们的本质 传统 ajax AJAX (几个单词首字母,按规范应该大写) - Asynchronous JavaScript and XML(异…...

Android Execution failed for task ‘:app:mergeDebugJavaResource

错误提示 FAILURE: Build failed with an exception.* What went wrong: Execution failed for task :app:mergeDebugJavaResource. > A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction> 2 files found with path k…...

spring事物源码分析

今天的任务是剖析源码,看看Spring 是怎么运行事务的,并且是基于当前最流行的SpringBoot。还有,我们之前剖析Mybatis 的时候,也知道,Mybatis 也有事务,那么,他俩融合之后,事务是交给谁…...

炫龙游戏本Win10系统总是蓝屏崩溃怎么办?

炫龙游戏本Win10系统总是蓝屏崩溃怎么办?有用户使用的炫龙游戏本最近总是在运行的过程中出现自动蓝屏的情况,有的时候自己还在操作电脑,而屏幕却蓝屏了,导致自己的工作被中断了。那么这个情况要怎么去进行修复呢?来看看…...

华为OD机试题,用 Java 解【数字加减游戏】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

C++ 手写一个高性能json生成与解析器

文章目录 前言一、了解json格式二、统一数据类型:TJson三、解析json数据四、输出json数据五、实现便利的修改与访问六、性能优化七、源码下载与解析前言 由于C++标准库中并不存在解析json数据库,但json格式又非常的常见 如今绝大部分网络数据传输都采用的json数据传输格式,…...

java——了解反射

目录 什么是反射? 反射如何获取类信息? 小结: 什么是反射? 反射是用代码分析类信息的能力 类中有哪些信息:方法、对象、构造器、全局变量、父类、接口等.... 反射如何获取类信息? 三种方式 1.通过对象…...

The Sandbox 中的独特体验——《奥米加》

在过去几年间,The Sandbox 游戏变得越来越受欢迎。因为我们为玩家提供了在虚拟世界中探索、创造和游戏的自由,没有线性游戏的限制。DeQuest 工作室创作的《奥米加》也正是如此,绝对是一个前所未有的体验! 先了解一下《奥米加》的故…...

76 Python写入csv文件时出现空行_newline参数解决

76 Python写入csv文件时出现空行_newline参数解决 文章目录76 Python写入csv文件时出现空行_newline参数解决1. 准备工作2. with open 语句没有newline参数3. with open 语句有newline参数4. 总结1. 准备工作 在电脑D盘新建一个【76】文件夹。 用VScode编辑器打开【76】文件夹…...

高等数学——定积分和不定积分

文章目录不定积分概念几何意义性质不定积分的基本公式三种主要积分法三类常见可积函数积分定积分概念几何意义性质积分上限的函数定积分的计算几何应用反常积分无穷区间的反常积分无界函数的反常积分不定积分 不定积分是导数的逆运算。 概念 原函数:设f(x)f(x)f(…...

imx6 usb增强信号强度

USB信号 参考:官方文档 USB信号完整性取决于许多因素,如电路设计、PCB布局、堆叠和阻抗。每个产品可能彼此不同,因此客户需要微调参数,以获得最佳的信号质量。 测试板已经路由出两个USB端口:一个OTG1,一个主机。每个端…...

深入理解性能压测工具原理

如果没有性能测试工具如何通过手工实现 如果没有性能测试工具,通过手工进行性能测试,这是一个值得我们思考的问题。这时候需要一个协调员发送指令,一个操作员进行操作,对系统施加压力,多个操作员代表着多个用户进行并…...

Java的概述和运行方式

目录 一.Java是什么? 1.1Java的目前状况和学习需求 1.2Java的平台分类和特点 二.Java程序的运行方式 2.1 Java的程序结构 2.2 JDK、JRE、JVM的关系 2.3 Java运行详情 总结 😽个人主页:tq02的博客_CSDN博客-领域博主 🌈理想…...