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

MySQL锁详解

MySQL锁详解

  • 数据库的锁机制
  • 锁的分类
    • 行级锁与表级锁
    • 行级锁之共享锁与排他锁
    • 乐观锁与悲观锁
      • 悲观锁
      • 乐观锁
  • Innodb存储引擎的锁机制
    • 行级锁与表级锁的使用区分
    • 三种行锁的算法
    • 死锁的问题
    • 多版本并发控制MVCC

数据库的锁机制

什么是锁?锁是一种保障数据的机制

为何要用锁?在并发访问情况下,可能会出现脏读、不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,以及事务隔离级别的概念,而锁机制可以将并发的数据访问顺序化,以保证数据库中数据的一致性与有效性

锁的分类

一、按锁的粒度划分,可分为行级锁、表级锁。(mysql支持)

二、按锁级别划分,可分为共享锁、排他锁

三、按使用方式划分,可分为乐观锁、悲观锁

四、按加锁方式划分,可分为自动锁、显式锁

五、按操作划分,可分为DML锁、DDL锁

行级锁与表级锁

行级锁

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

  • 特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
  • 支持引擎:InnoDB
  • 行级锁分为行共享读锁(共享锁)与行独占写锁(排他锁),如下所示
  • 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
  • 排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE

表级锁(偏向于读)

表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAN与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

  • 特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
  • 支持引擎:MYISAM、INNODB
  • 分类:表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁),如下所示
  • lock table 表名 read(write),表名 read(write),.....;

总结:

  • 优点:保障并发场景下的数据安全
  • 缺点:降低了效率
  • 所以我们在使用锁时应该尽可能缩小锁的范围,即锁住的数据越少越好,并发能力越高

行级锁之共享锁与排他锁

行级锁分为共享锁和排他锁两种。与行处理相关的sql有:insert、update、delete、select,这四类sql在操作记录行时,可以为行加上锁,但需要知道的是

  • 对于insert、update、delete语句,InnoDB会自动给涉及的数据加锁,而且是排他锁(X);
  • 对于普通的select语句,InnoDB不会加任何锁,需要我们手动自己加,可以加两种类型的锁,如下所示
  • 共享锁(S):SELECT ... LOCK IN SHARE MODE; --查出的记录行都会被锁住(别人写不行,但是可以读)
  • 排他锁(X):SELECT ... FOR UPDATE; – 查出的记录行都会被锁住(别人写不行,但是可以读)

共享锁(Share Lock)

共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,获取到共享锁的事务只能读数据,不能修改数据直到已释放所有共享锁,所以共享锁可以支持并发读。

如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁或不加锁(在其他事务里一定不能再加排他锁,但是在事务T自己里面是可以加的),反之亦然。

用法:SELECT ... LOCK IN SHARE MODE;

在查询语句后面增加 LOCK IN SHARE MODE,Mysql会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。

排他锁(exclusive Lock)

排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再对该行加任何类型的其他锁(共享锁和排他锁),但是获取排他锁的事务是可以对数据就行读取和修改。

用法:SELECT ... FOR UPDATE;

在查询语句后面增加 FOR UPDATE,Mysql会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

特例:加过排他锁的数据行在其他事务中是不能修改数据的,也不能通过 for update 和 lock in share mode 锁的方式查询数据,但可以直接通过 select … from … 查询数据,因为普通select查询没有任何锁机制。

乐观锁与悲观锁

数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时读取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。

乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想。其实不仅仅是关系型数据库系统中有乐观锁和悲观锁的概念,像memcache、hibernate、tair等都有类似的概念。

针对于不同的业务场景,应该选用不同的并发控制方式。所以不要把乐观并发控制和悲观并发控制狭义的理解为DBMS中的概念,更不要把他们和数据中提供的锁机制(行锁、表锁、排他锁、共享锁)混为一谈。在DBMS中,悲观锁正是利用数据库本身提供的锁机制来实现的。

悲观锁

当我们要对一个数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制在修改数据之前先锁定,再修改的方式被称之为悲观并发控制(又名“悲观锁”,Pessimistic concurrency control,缩写“PCC”)。在关系数据库管理系统里,悲观并发控制是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作对某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度(悲观),因此在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据),现在互联网高并发的架构中,受到 fail-fast 思路的影响,悲观锁已经非常少见了。

在数据库中,悲观锁的流程如下:

  1. 在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
  2. 如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。
  3. 如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
  4. 其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。

ps:行锁、表锁、读锁、写锁都是在操作之前先上排他锁

在数据表中的实现:在MySQL中使用悲观锁,必须关闭MySQL的自动提交,set autocommit=0,因为MySQL默认使用自动提交autocommit模式,在执行完sql后会自动提交并释放锁

总结

  • 悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。
  • 优点:悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。
  • 缺点:在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数。

乐观锁

在关系数据库管理系统里,乐观并发控制(又名“乐观锁",optimistic concurrency control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。

乐观锁( optimistic Locking) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般实现乐观锁的方式就是记录数据版本。

数据版本:为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。

在数据库中,乐观锁的实现有两种方式

1、使用版本号实现

  • 每一行数据多一个字段version,每次更新数据对应版本号+1,
  • 原理:读出数据,将版本号一同读出,之后更新,版本号+1,提交数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据,重新读取数据

2、使用时间戳实现

  • 每一行数据多一个字段time
  • 原理:读出数据,将时间戳一同读出,之后更新,提交数据时间戳等于数据库当前时间戳,则予以更新,否则认为是过期数据,重新读取数据

乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁,。而乐观锁也需要灵活运用

总结:在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了

  • 乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。
  • 悲观锁依赖数据库锁,效率低。更新失败的概率比较低。
  • 随着互联网三高架构(高并发、高性能、高可用)的提出,悲观锁已经越来越少的被使用到生产环境中了,尤其是并发量比较大的业务场景。

Innodb存储引擎的锁机制

mysql常用存储引擎的锁机制

  • MyISAM采用表级锁(table-level locking)
  • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁(偏向于写)(主要)

行级锁与表级锁的使用区分

MyISAM 操作数据都是使用表级锁,MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。所以不会产生死锁,但是由于每操作一条记录就要锁定整个表,导致性能较低,并发不高。

InnoDB 与 MyISAM 的最大不同有两点:一是InnoDB支持事务;二是InnoDB采用了行级锁。

在Mysql中,行级锁并不是直接锁记录,而是锁索引。InnoDB 行锁是通过给索引项加锁实现的,而索引分为主键索引和非主键索引两种

  1. 如果一条sql语句操作了主键索引,Mysql 就会锁定这条语句命中的主键索引(或称聚簇索引)
  2. 如果一条语句操作了非主键索引(或称辅助索引),MySQL会先锁定该非主键索引,再锁定相关的主键索引。
  3. 如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表级锁一样。
  4. 强调:命中了索引才会锁行,不是说有索引就可以锁行

在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能

  1. 在不通过索引条件查询的时候,InnoDB 的效果就相当于表锁
  2. 当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外不论是使用主键索引、唯一索引或普通索引,InnoD8 都会使用行锁来对数据加锁。
  3. 由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以即便你的sql语句访问的是不同的记录行,但如果命中的是相同的被锁住的索引键,也还是会出现锁冲突的。
  4. 即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同执行计划的代价来决定的,如果 MySQL认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下 InnoDB 将锁住所有行,相当于表锁。因此,在分析锁冲突时,别忘了检查 SQL 的执行计划,以确认是否真正使用了索引。

绝大部分情况使用行锁,但在个别特殊事务中,也可以考虑使用表锁

  • 事务需要更新大部分数据,表又较大
  • 若使用默认的行锁,不仅该事务执行效率低(因为需要对较多行加锁,加锁是需要耗时的),而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度
  • 事务涉及多个表,较复杂,很可能引起死锁,造成大量事务回滚
  • 这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销,当然应用中这两种事务也不能太多

三种行锁的算法

InnoDB有三种行锁的算法,都属于排他锁:

1、Record Lock(记录锁)

单个行记录上的锁

2、Gap Lock(间隙锁)

间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读出现幻读的情况。

当用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)",InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

例:假如employee表中只有101条记录,其depid的值分别是1,2,…,100,101,下面的SQL:select * from emp where depid >100 for update; 是一个范围条件的检索,并且命中了索引,InnoDB不仅会对符合条件的dempid值为101的记录加锁,也会对dempid大于101(这些记录并不存在)的“间隙”加锁。

3、Next-Key Lock(间隙锁定)

等于Record Lock结合Gap Lock,也就说Next-Key Lock既锁定记录本身也锁定一个范围,特别需要注意的是,InnoDB存储引擎还会对辅助索引下一个键值加上gap lock。

对于行查询,innodb采用的都是Next-Key Lock,主要目的是解决幻读的问题,以满足相关隔离级别以及恢复和复制的需要。

总结:

  1. 如果没有命中索引,无论你筛选出哪一行,都会将整张表锁住
  2. 如果命中了非唯一索引,并且是等值查询,会锁行还有间隙
  3. 如果命中了非唯一索引,但是是范围查询,会锁行还有间隙
  4. 如果命中了唯一索引,并且是等值查询,只会锁定行
  5. 如果命中了唯一索引,并且是范围查询,会锁行还有间隙

死锁的问题

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进程称为死锁进程。

MYISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在INNODB中,锁是逐步获得的,就造成了死锁的可能。

范例1:两个Session的两条SQL产生死锁

# 事务1
begin; -- 步骤1
select * from t1 where id=1 for update; -- 步骤2
update t1 set name="Alan" where id=5; -- 步骤5
# 事务2:
begin; -- 步骤3
select * from t1 where id=5 for update; -- 步骤4
delete from t1 where id=1; -- 步骤6

当执行步骤6的时候就会产生死锁,这个相当于每个事务执行两条SQL,分别持有了一把锁,然后加另一把锁,产生死锁,这个非常好理解,也是最常见的死锁。

范例2:两个Session的一条SQL产生死锁

在这里插入图片描述
如上图所示,只有多个事务同时运行的情况下才可能出现,但隐蔽性极强,虽然每个session都只有一条语句,仍旧会产生死锁。要分析这个死锁,首先必须用到本文前面提到的MySQL加锁的规则。针对session1,从name索引出发,读到的 [hdc,1],[hdc,6] 均满足条件,不仅会加name索引上的记录X锁,而且会加聚族索引上的记录X锁,加锁顺序为先[1,hdc,100],后[6,hdc,10]。而session2,从pubtime索引出发,[10,6],[100,1] 均满足过滤条件,同样也会加聚簇索引上的记录X锁,加锁顺序为[6,hdc,10],后[1,hdc,100]。发现没有,跟session1的加锁顺序正好相反,如果两个session恰好都持有了第一把锁,请求加第二把锁,死锁就发生了。

总结:一般会在高并发场景下发生,核心原理是命中了辅助索引,会先锁定辅助索引,再锁定聚集索引。一般这个情况下由后端开发人员修改逻辑语句。

结论:

1、关于死锁问题需要储备的知识

  • 在MySQL中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种
  • 如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引
  • 如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引
  • 在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的 next-key locking

2、死锁产生的本质原理

  • 死锁的发生与否,并不在于事务中有多少条SQL语句,死锁的关键在于两个(或以上)的session加锁的顺序不一致。
  • 而使用本文上面提到的,分析MySQL每条SQL语句的加锁规则,分析出每条语句的加锁顺序,然后检查多个并发SQL间是否存在以相反的顺序加锁的情况,就可以分析出各种潜在的死锁情况,也可以分析出线上死锁发生的原因。

发生死锁后,InnoDB一般都可以检测到,并使一个事务释放锁回退,另一个获取锁完成事务。以下有多种方法可以避免死锁:

  • 如果不同程序会并发读取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会;
  • 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
  • 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;
  • 在程序以批量方式处理数据的时候,如果事先对数据排序,保证每个线程按固定的顺序来处理记录,也可以大大降低出现死锁的。

多版本并发控制MVCC

MySQL的InnoDB存储引擎,实现的是基于多版本的并发控制协议–MVCC([Multi-Version concurrency contro]]

与MVVC相对的,是基于锁的并发控制(Lock-Based Concurency Control)。MVCC最大的好处,就是读不加锁,读写不冲突。在读多写少的DLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,这也是为什么现阶段,几乎所有的RDBMS,都支持了MVCC。

在MVCC并发控制中,读操作可以分成两类:快照读(snapshot read)与当前读(current read)。快照读,读取的是记录的可见版本(有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

在一个支持MVCC并发控制的系统中,哪些读操作是快照读?哪些操作又是当前读呢?以MySQL InnoDB为例:

  1. 快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外)
    select * from table where ?;

  2. 当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
    select * from table where ? lock in share mode;
    select * from table where ? for update;
    insert into table values (...);
    update table set ? where ?;
    delete from table where ?;

所有以上当前读的语句中,都读取的是记录的最新版本。并且读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中除了第一条语句,对读取记录加S锁(共享锁)外,其他的操作都加的是X锁(排它锁)。

相关文章:

MySQL锁详解

MySQL锁详解 数据库的锁机制锁的分类行级锁与表级锁行级锁之共享锁与排他锁乐观锁与悲观锁悲观锁乐观锁 Innodb存储引擎的锁机制行级锁与表级锁的使用区分三种行锁的算法死锁的问题多版本并发控制MVCC 数据库的锁机制 什么是锁?锁是一种保障数据的机制 为何要用锁…...

快速提升网站收录:利用网站用户反馈机制

本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/59.html 利用网站用户反馈机制是快速提升网站收录的有效策略之一。以下是一些具体的实施步骤和建议: 一、建立用户反馈机制 多样化反馈渠道: 设立在线反馈表、邮件…...

初五,很棒

20元一瓶的水见过没?配料只有水和维C,养生佳品?除非我疯了。 今晚和大姨爹等人探讨成家问题。没错,我变成最应该成家的人了。 的确,从年龄上,发展阶段上,也是应该成家啦。 难道我不知道嘛。 人…...

Vue指令v-html

目录 一、Vue中的v-html指令是什么?二、v-html指令与v-text指令的区别? 一、Vue中的v-html指令是什么? v-html指令的作用是:设置元素的innerHTML,内容中有html结构会被解析为标签。 二、v-html指令与v-text指令的区别…...

ubuntu磁盘扩容

ubuntu磁盘扩容 描述先在虚拟机设置里面扩容进入Ubuntu 配置使用命令行工具parted进行分区输出如下完成 描述 执行命令,查看 fs 类型是什么 lsblk -o NAME,FSTYPE,MOUNTPOINT将60G扩容到100G,其中有些操作我也不知道什么意思,反正就是成功了&#xff0…...

BFS(广度优先搜索)——搜索算法

BFS,也就是广度(宽度)优先搜索,二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS(深度优先搜索)。从字面意思也很好理解,DFS就是一条路走到黑,BFS则是一层一层地展开。…...

SAP SD学习笔记27 - 请求计划(开票计划)之1 - 定期请求(定期开票)

上两章讲了贩卖契约(框架协议)的概要,以及贩卖契约中最为常用的 基本契约 - 数量契约和金额契约。 SAP SD学习笔记26 - 贩卖契约(框架协议)的概要,基本契约 - 数量契约_sap 框架协议-CSDN博客 SAP SD学习笔记27 - 贩卖契约(框架…...

string例题

一、字符串最后一个单词长度 题目解析:由题输入一段字符串或一句话找最后一个单词的长度,也就是找最后一个空格后的单词长度。1.既然有空格那用我们常规的cin就不行了,我们这里使用getline,2.读取空格既然是最后一个空格后的单词,…...

Revit二次开发 自适应族添加放样融合

大多数博客给出的方案都是如何在有自适应族的情况下进行修改定位点或是将数据传入自适应族,如何直接在族文件中创建自适应模型并将点转换为自适应点,连接自适应点成为自适应路径这种方式没有文章介绍. 下面的代码中给出了如何在自适应族文件中创建参照点并转换为自适应点连接…...

浏览器模块化难题

CommonJS 的工作原理 当使用 require(模块路径) 导入一个模块时,node会做以下两件事情(不考虑模块缓存): 通过模块路径找到本机文件,并读取文件内容将文件中的代码放入到一个函数环境中执行,并将执行后 m…...

详细介绍:网站背景更换功能

目录 1. HTML 部分 2. JavaScript 部分 3. 完整流程 4. 总结 5. 适用场景 本文将介绍如何通过文件上传实现网站背景图片的更换。通过使用 JavaScript 和 Axios,我们可以允许用户上传图片文件并将其作为网站的背景图片。上传的图片 URL 会保存在浏览器的 localSt…...

w190工作流程管理系统设计与实现

🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...

Linux——文件系统

一、从硬件出发 1)磁盘的主要构成 通常硬盘是由盘片、主轴、磁头、摇摆臂、马达、永磁铁等部件组成,其中一个硬盘中有多块盘片和多个磁头,堆叠在一起,工作时由盘片旋转和摇摆臂摇摆及逆行寻址从而运作,磁头可以对盘片…...

傅里叶分析之掐死教程

https://zhuanlan.zhihu.com/p/19763358 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析 不仅仅是一个数学工具,更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是,傅里叶分析的公式看起来太复杂了,所以很多…...

使用scikit-learn中的K均值包进行聚类分析

聚类是无监督学习中的一种重要技术,用于在没有标签信息的情况下对数据进行分析和组织。K均值算法是聚类中最常用的方法之一,其目标是将数据点划分为K个簇,使得每个簇内的数据点更加相似,而不同簇之间的数据点差异较大。 准备自定…...

Compose笔记(一)--LifecycleEventObserver

这一节了解一下LifecycleEventObserver,它在 Android Compose 中是一个接口,它允许你监听 Android 组件(如 Activity、Fragment)的生命周期事件。Lifecycle 代表 Android 组件从创建到销毁的整个生命周期,而 Lifecycle…...

算法总结-二分查找

文章目录 1.搜索插入位置1.答案2.思路 2.搜索二维矩阵1.答案2.思路 3.寻找峰值1.答案2.思路 4.搜索旋转排序数组1.答案2.思路 5.在排序数组中查找元素的第一个和最后一个位置1.答案2.思路 6.寻找旋转排序数组中的最小值1.答案2.思路 1.搜索插入位置 1.答案 package com.sunxi…...

MySQL(InnoDB统计信息)

后面也会持续更新,学到新东西会在其中补充。 建议按顺序食用,欢迎批评或者交流! 缺什么东西欢迎评论!我都会及时修改的! 大部分截图和文章采用该书,谢谢这位大佬的文章,在这里真的很感谢让迷茫的…...

Spring Cloud工程搭建

目录 工程搭建 搭建父子工程 创建父工程 Spring Cloud版本 创建子项目-订单服务 声明项⽬依赖 和 项⽬构建插件 创建子项目-商品服务 声明项⽬依赖 和 项⽬构建插件 工程搭建 因为拆分成了微服务,所以要拆分出多个项目,但是IDEA只能一个窗口有一…...

MySQL锁类型(详解)

锁的分类图,如下: 锁操作类型划分 读锁 : 也称为共享锁 、英文用S表示。针对同一份数据,多个事务的读操作可以同时进行而不会互相影响,相互不阻塞的。 写锁 : 也称为排他锁 、英文用X表示。当前写操作没有完成前,它会…...

Kafka SASL/SCRAM介绍

文章目录 Kafka SASL/SCRAM介绍1. SASL/SCRAM 认证机制2. SASL/SCRAM 认证工作原理2.1 SCRAM 认证原理2.1.1 密码存储和加盐2.1.2 SCRAM 认证流程 2.2 SCRAM 认证的关键算法2.3 SCRAM 密码存储2.4 SCRAM 密码管理 3. 配置和使用 Kafka SASL/SCRAM3.1 Kafka 服务器端配置3.2 创建…...

使用VCS进行单步调试的步骤

使用VCS对SystemVerilog进行单步调试的步骤如下: 1. 编译设计 使用-debug_all或-debug_pp选项编译设计,生成调试信息。 我的4个文件: 1.led.v module led(input clk,input rst_n,output reg led );reg [7:0] cnt;always (posedge clk) beg…...

计算机网络 应用层 笔记1(C/S模型,P2P模型,FTP协议)

应用层概述: 功能: 常见协议 应用层与其他层的关系 网络应用模型 C/S模型: 优点 缺点 P2P模型: 优点 缺点 DNS系统: 基本功能 系统架构 域名空间: DNS 服务器 根服务器: 顶级域…...

Node.js下载安装及环境配置

目录 一、下载 1. 查看电脑版本,下载对应的安装包 2. 下载路径下载 | Node.js 中文网 二、安装步骤 1. 双击安装包 2. 点击Next下一步 3. 选择安装路径 4. 这里我选择默认配置,继续Next下一步(大家按需选择) 5. 最后inst…...

LeetCode题练习与总结:任务调度器--621

一、题目描述 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表,用字母 A 到 Z 表示,以及一个冷却时间 n。每个周期或时间间隔允许完成一项任务。任务可以按任何顺序完成,但有一个限制:两个 相同种类 的任务之间必须有长…...

动手学深度学习-3.2 线性回归的从0开始

以下是代码的逐段解析及其实际作用: 1. 环境设置与库导入 %matplotlib inline import random import torch from d2l import torch as d2l作用: %matplotlib inline:在 Jupyter Notebook 中内嵌显示 matplotlib 图形。random:生成…...

鸿蒙HarmonyOS Next 视频边播放边缓存- OhosVideoCache

OhosVideoCache 是一个专为OpenHarmony开发(HarmonyOS也可以用)的音视频缓存库,旨在帮助开发者轻松实现音视频的边播放边缓存功能。以下是关于 OhosVideoCache 的详细介绍: 1. 核心功能 边播放边缓存:将音视频URL传递给 OhosVideoCache 处理后…...

#systemverilog# Verilog与SystemVerilog发展历程及关系

1. Verilog的发展历史 1984年:Gateway Design Automation公司开发了Verilog,最初作为专有语言,用于逻辑仿真和数字电路设计。 1990年:Cadence收购Gateway,Verilog逐步开放,成为行业标准。 1995年(IEEE 1364-1995):首个IEEE标准,即Verilog-1995,定义基础语法和仿真语…...

【集成Element Plus】

集成Element Plus 安装main.ts中全局引入安装图标库 安装 pnpm add element-plusmain.ts中全局引入 import ElementPlus from element-plus; import element-plus/dist/index.css;app.use(ElementPlus);安装图标库 pnpm install element-plus/icons-vue...

基于微信小程序的电子商城购物系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

进阶数据结构——双向循环链表

目录 前言一、定义与结构二、特点与优势三、基本操作四、应用场景五、实现复杂度六、动态图解七、代码模版(c)八、经典例题九、总结结语 前言 这一期我们学习双向循环链表。双向循环链表不同于单链表,双向循环链表是一种特殊的数据结构&…...

Kafka分区策略实现

引言 Kafka 的分区策略决定了生产者发送的消息会被分配到哪个分区中,合理的分区策略有助于实现负载均衡、提高消息处理效率以及满足特定的业务需求。 轮询策略(默认) 轮询策略是 Kafka 默认的分区策略(当消息没有指定键时&…...

【hot100】560和为K的子数组

一、思路 初步思路就是采用双循环以每个节点为头节点,然后向后遍历是否有满足和为K的子数组。 然后我们可以采用另一个新的思路,就是可以采用“前缀和的思路”,具体就是如果hashmap中存在sum-k的值,那就可以说明存在一个何为k的…...

【01】共识机制

BTF共识 拜占庭将军问题 拜占庭将军问题是一个共识问题 起源 Leslie Lamport在论文《The Byzantine Generals Problem》提出拜占庭将军问题。 核心描述 军中可能有叛徒,却要保证进攻一致,由此引申到计算领域,发展成了一种容错理论。随着…...

树莓派pico入坑笔记,故障解决:请求 USB 设备描述符失败,故障码(43)

今天心血来潮,拿出吃灰的pico把玩一下,打开thonny,上电,然后...... 上电识别不到端口,windows报错,请求 USB 设备描述符失败,故障码(43) 一开始以为是坏了(磕…...

大语言模型的个性化综述 ——《Personalization of Large Language Models: A Survey》

摘要: 本文深入解读了论文“Personalization of Large Language Models: A Survey”,对大语言模型(LLMs)的个性化领域进行了全面剖析。通过详细阐述个性化的基础概念、分类体系、技术方法、评估指标以及应用实践,揭示了…...

线程互斥同步

前言: 简单回顾一下上文所学,上文我们最重要核心的工作就是介绍了我们线程自己的LWP和tid究竟是个什么,总结一句话,就是tid是用户视角下所认为的概念,因为在Linux系统中,从来没有线程这一说法,…...

高效接口限流:基于自定义注解与RateLimiter的实践

在高并发场景下,接口的流量控制是保证系统稳定性和提升性能的关键之一。通过实现接口限流,我们可以有效避免系统在访问高峰时发生崩溃。本文将详细介绍如何通过自定义注解和切面编程结合RateLimiter来实现接口的限流功能,以应对高并发请求。 …...

嵌入式硬件篇---HAL库内外部时钟主频锁相环分频器

文章目录 前言第一部分:STM32-HAL库HAL库编程优势1.抽象层2.易于上手3.代码可读性4.跨平台性5.维护和升级6.中间件支持 劣势1.性能2.灵活性3.代码大小4.复杂性 直接寄存器操作编程优势1.性能2.灵活性3.代码大小4.学习深度 劣势1.复杂性2.可读性3.可维护性4.跨平台性…...

万字长文深入浅出负载均衡器

前言 本篇博客主要分享Load Balancing(负载均衡),将从以下方面循序渐进地全面展开阐述: 介绍什么是负载均衡介绍常见的负载均衡算法 负载均衡简介 初识负载均衡 负载均衡是系统设计中的一个关键组成部分,它有助于…...

使用递归解决编程题

题目:递归实现组合型枚举 从 1−n 这 n 个整数中随机选取 m 个,每种方案里的数从小到大排列,按字典序输出所有可能的选择方案。 输入 ​输入两个整数 n,m。(1≤m≤n≤10) 输出 每行一组方案,每组方案中…...

Nginx 中文文档

文章来源:nginx 文档 -- nginx中文文档|nginx中文教程 nginx 文档 介绍 安装 nginx从源构建 nginx新手指南管理员指南控制 nginx连接处理方法设置哈希调试日志记录到 syslog配置文件测量单位命令行参数适用于 Windows 的 nginx支持 QUIC 和 HTTP/3 nginx 如何处理…...

2.策略模式(Strategy)

定义 定义一系列算法,把它们一个个封装起来,并且使他们可互相替换(变化)。该模式使算法可独立于使用它的客户程序(稳定)而变化(拓展,子类化)。 动机(Motiva…...

浔川AI翻译v6.0延迟上线说明

浔川社团官方联合会关于浔川AI翻译v6.0版本的说明 尊敬的各位用户: 大家好! 首先,衷心感谢大家一直以来对浔川社团官方联合会以及浔川AI翻译的关注与支持。在此,我们怀着十分遗憾的心情向大家发布一则重要通知:原计划推…...

git基础使用--4---git分支和使用

文章目录 git基础使用--4---git分支和使用1. 按顺序看2. 什么是分支3. 分支的基本操作4. 分支的基本操作4.1 查看分支4.2 创建分支4.3 切换分支4.4 合并冲突 git基础使用–4—git分支和使用 1. 按顺序看 -git基础使用–1–版本控制的基本概念 -git基础使用–2–gti的基本概念…...

[paddle] 矩阵相关的指标

行列式 det 行列式定义参考 d e t ( A ) ∑ i 1 , i 2 , ⋯ , i n ( − 1 ) σ ( i 1 , ⋯ , i n ) a 1 , i 1 a 2 , i 2 , ⋯ , a n , i n det(A) \sum_{i_1,i_2,\cdots,i_n } (-1)^{\sigma(i_1,\cdots,i_n)} a_{1,i_1}a_{2,i_2},\cdots, a_{n,i_n} det(A)i1​,i2​,⋯,in​…...

CH340G上传程序到ESP8266-01(S)模块

文章目录 概要ESP8266模块外形尺寸模块原理图模块引脚功能 CH340G模块外形及其引脚模块引脚功能USB TO TTL引脚 程序上传接线Arduino IDE 安装ESP8266开发板Arduino IDE 开发板上传失败上传成功 正常工作 概要 使用USB TO TTL(CH340G)将Arduino将程序上传…...

CMake的QML项目中使用资源文件

Qt6.5的QML项目中,我发现QML引用资源文件并不像QtWidgets项目那样直接。 在QtWidgets的项目中,我们一般是创建.qrc​资源文件,然后创建前缀/new/prefix​,再往该前缀中添加一个图片文件,比如:test.png​。…...

FBX SDK的使用:读取Mesh

读取顶点数据 要将一个Mesh渲染出来,必须要有顶点的位置,法线,UV等顶点属性,和三角面的顶点索引数组。在提取这些数据之前,先理解FBX SDK里面的几个概念: Control Point 顶点的位置,就是x,y,z…...

无人机PX4飞控 | PX4源码添加自定义uORB消息并保存到日志

PX4源码添加自定义uORB消息并保存到日志 0 前言 PX4的内部通信机制主要依赖于uORB(Micro Object Request Broker),这是一种跨进程的通信机制,一种轻量级的中间件,用于在PX4飞控系统的各个模块之间进行高效的数据交换…...