当前位置: 首页 > 后端技术 > Node.js

Mysql的锁机制

时间:2023-04-03 10:33:00 Node.js

本文首发于公众号:程序员周先森。本平台不定期更新,喜欢我的文章,请关注我的微信公众号。锁是一种机制,计算机通过该机制协调多个进程或线程对资源的并发访问。数据库中的数据实际上是大量用户共享的资源,因此我们需要保证数据在并发访问时的一致性和有效性,而锁冲突是影响数据库并发性能的最关键因素之一。所以本文主要讨论Mysql中锁机制的特点。Mysql的锁机制包括多种类型:行锁、表锁、读锁、写锁等,其实不同的存储引擎会支持不同的锁机制。而我主要介绍InnoDB存储引擎下的7种锁。InnoDB引擎锁类型:共享/排他锁、记录锁、间隙锁、邻键锁、自增锁、意向锁、插入意向锁,MySQLInnoDB存储引擎和MyISAM存储引擎的锁机制,其实有两个显着区别:InnoDB支持事务操作。InnoDB默认使用行级锁。InnoDB锁机制实现原理InnoDB存储引擎实际上是在索引上对索引项加锁。正是因为索引项上有锁,InnoDB引擎只有在通过索引条件查询数据时,才会选择使用行级锁,否则就会使用表锁。行级锁和表级锁有很多区别,事务的引入也带来了一些新的问题。说到事务,我想大多数人都不能理解最基本的四个特性:原子性:事务是一个原子操作单元,它对数据的修改要么执行要么根本不执行。一致性:数据必须在事务的开始和结束时保持一致的状态。隔离性:事务处理过程中的中间状态对外界是不可见的。持久性:事务完成后,其对数据的修改是永久性的。并发问题并发事务处理可以大大提高数据库资源的利用率,提高数据库系统的事务吞吐量。但是,如果在并发事务处理中没有加锁,会存在几个问题:更新丢失:两个事务同时更新同一个数据,先更新的数据会被后更新的数据替代,导致在数据丢失。脏读:两个事务之一负责更新操作,另一个负责查询操作。update操作已经更新了数据但是还没有提交数据。这时候查询的数据就会出现数据不一致,也就是我们常说的脏数据。不可重复读:事务在读取数据后的某个时间再次读取相同的数据,却发现获取的数据发生了变化。幻读:第一个事务查询数据,重复读取相同的数据,第二次检索得到的数据比第一次新,称为幻读。Shared/exclusivelock这种锁机制其实有两种锁:sharedlock和exclusivelock。读取数据时使用共享锁,可以并行操作,即读取数据操作可以并发进行。修改数据时使用独占锁。排他锁和任意锁是互斥的,即修改数据和其他操作,无论是读还是修改,都不能并发执行。顾名思义,记录锁记录锁块记录。比如我们要查找学号sid为1的学生信息,使用排他锁就会锁住这一行记录,其他事务就不能对这一行数据进行操作。记录锁其实就是先获取这张数据表的意向排他锁,也就是说这个事务打算给这张数据表中的一些数据加一个排他锁,然后获取这行数据的排他锁,此时其他事务是不可能对这一行数据进行操作的。那么什么是意向排他锁呢?接下来,让我们看一下意向锁。意向锁之所以会出现意向锁,其实就是为了让行级锁和表级锁能够共存。意向锁其实就是我刚才说的。这个事务需要在以后的某个时间点锁定某个数据表,先跟大家说说。表明你的意图。意向锁是表级锁,也分为意向共享锁和意向排他锁,但与共享排他锁的一个区别是意向锁是相互兼容的,也就是说无论是意向排他锁还是意向排他锁意向共享锁。锁是相互兼容的,但是意向锁与独占锁不兼容,因为独占锁与任何其他锁都不兼容。间隙锁间隙锁的出现其实就是为了防止不可重复读。间隙锁可用于向字段添加间隔限制。比如我们查询id=1的数据,我们可以给id为1的数据加gap锁,这样在这个事务结束之前,其他数据就无法更新id为1的数据,也就是non的问题-可解决重复读。如果事务的隔离级别设置为readcommitted,则间隙锁无法生效。相邻键锁相邻键锁实际上同时作用于索引间隙和索引记录,即记录锁和间隙锁的组合。默认情况下,使用临时键锁同时锁定索引记录和索引间隙,即双重锁定。但是,如果索引是唯一索引或主键索引,则使用记录锁只锁定索引本身,不加间隙锁,所以如果一个字段有唯一值,可以添加唯一索引来提高性能。InsertintentlockInsertintentlock是作用于索引的锁,专门用于insert操作。这个锁可以由多个事务共同操作。多个事务同时操作同一个索引。插入记录时,如果插入位置不冲突,则插入操作不会相互影响。比如我们的两个事务是同时进行的,分别插入id为1和id为2的记录。因为id不冲突,所以不会互相阻塞。自增锁自增锁很明显是用于自增类型的操作。自增锁是表级锁。自增锁的作用是保证数据库的主键自动递增。其实这个锁主要用于对主键自增的数据表的插入操作。两个事务先后执行插入操作,第二个事务的插入操作会因为主键需要自增而阻塞。表锁的注意事项刚才说了,InnoDB默认使用行级锁,但其实有时候像意向锁这样的表级锁更合适。例如,当一个事务中需要更新大部分数据时,使用表锁可以提高事务性能。执行任务。也就是说,一个事务中涉及多张表的操作,如果出现死锁,会导致大量操作回滚。因此,这种情况下,可以直接对涉及到的所有表加表锁,这样可以减少出现死锁的可能性。概率,减少数据库的开销。避免死锁的解决方法死锁实际上是两个事务在执行过程中因为争夺资源而相互等待的一种现象。这时候就出现了死锁。造成死锁的关键原因其实是两个事务加锁的顺序不一致,然后互相持有对方的资源不释放等待对方的资源。当发生死锁时,InnoDB引擎可以自动检测并回滚一个事务来解决死锁问题。但是,当涉及表锁或外部锁时,不能保证检测到死锁的存在。因此,我们需要了解避免死锁的解决方案。一般有以下几种策略:预防死锁:破坏死锁的必要条件中的任何一个都可以防止死锁。例如,用户在申请资源时,要求一次性申请所有需要的资源,破坏了持有和等待的条件;资源是分层的,只有获得上层的资源才能申请下一层的资源,破坏了循环。等待条件。预防通常会降低系统的效率。避免死锁:避免死锁是指进程在每次申请资源的时候都会判断这些操作是否安全,比如使用银行家算法。死锁避免算法的执行会增加系统的开销。死锁检测:死锁预防和避免是事前措施,死锁检测是判断系统是否处于死锁状态,如果是则执行解除死锁策略。死锁释放:这个是和死锁检测配合使用的,使用方式是抢占。即强行收回某个进程拥有的资源,分配给其他进程。欢迎关注公众号:程序员周先森。文章原发于微信公众号,本平台不定时更新。