专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

MySQL锁机制详解(表级锁页级锁行级锁)

  MySQL的锁知识,跟索引知识一样,都同样的复杂,甚至更复杂。所以还需要一些耐心哟!MySQL中锁的分类
  下图为MySQL部分存储引擎所支持的锁
  MySQL支持三种层级的锁定
  我们知道,MySQL支持三种层级的锁定,分别为:表级锁定
  表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定页级锁定
  页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁行级锁定
  行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大
  从上到下,锁的粒度逐渐细粒化,但实现开销逐渐增大。同时我们也要须知,表锁,页锁,行锁并不是一个具体的锁,仅代表将数据库某个层级上的数据进行锁定。具体怎么去锁这个数据,还要看具体的锁实现是什么
  如何学习MySQL中的锁知识
  说实话,MySQL的锁知识,在初学的时候,真的是挺复杂的。主要是概念多,分类也多,还有各种乱七八糟,想到都烦的名词。所以学习MySQL中各种锁时,要从简单的入手,繁琐的名词暂时不要管。等有经验之后,自然会懂得。(一)了解MySQL大致有哪些锁,建立脑图分类知道MySQL支持三个层级的锁定,但要跟不同的存储引擎来判断数据库支持哪个层级的锁知道什么是表锁,行锁。什么是页锁(二)站在存储引擎的角度,具体学习存储引擎支持的锁知道不同存储引擎支持哪个层级的锁,主要研究InnoDB和MyISAM两种存储引擎研究MyISAM存储引擎下的表锁研究InnoDB存储引擎下的表锁和行锁研究InnoDB的排他锁和共享锁研究InnoDB的意向锁(三)重点研究InnoDB行锁的具体实现算法研究InnoDB的记录锁,间隙锁,临键锁(四)了解InnoDB下锁与事务,锁与索引的联系了解InnoDB下的RR级别下是怎么避免幻读的?了解锁与事务之间的联系,二段锁提交
  了解了以上的内容,我想应该大致也能够应付很多日常的开发了。剩下的内容比较细致和繁琐,个人觉得还是需要实际的社会实践,才能更加的深有体会并记住。事务持有锁的SQL
  要认识事务,SQL,与锁的知识,最好的办法就是调试。所以我这里提供给大家MySQL8。0以及MySQL8。0以下的查询事务持有锁情况的SQLMySQL8。0以下showengineinnodbstatus;
  在TRANSACTION位置可以看到事务持有锁的情况,但是需要经验分析,名词比较难懂selectfrominformationschema。innodblocks;
  查看innodb引擎下,所有表所有事务的加锁情况,无法分别gap,record,nextkey锁的具体类型。没有冲突情况无法显示持有的锁selectfrominformationschema。innodblockswait;
  查看innodb引擎下,所有表所有事务因锁的阻塞情况,谁被谁block住了MySQL8。0showengineinnodbstatus;
  在TRANSACTION位置可以看到事务持有锁的情况,但是需要经验分析,名词比较难懂selectfromperformanceschema。datalocks;
  查看数据库中所有表所有事务的加锁情况,没有冲突,也看到持有了什么锁,具有具体的分类,简单好用,更容易分析selectfromperformanceschema。datalockswait;
  查看数据库中,所有表所有事务因锁的阻塞情况,谁被谁block住了
  所以我个人建议还是用MySQL8。0的分析语句来调试更好,因为更加清晰,内容更多,功能更强大。MyISAM引擎所支持的锁MyISAM引擎的表锁
  MyISAM只支持表锁,不支持行锁和页面锁。据我查到的资料中,MyISAM引擎支持的锁不多,也就是表级的排他锁和共享锁而已,官方资料上也没有专门介绍MyISAM锁的章节表锁并不是一个真正的锁,只是代表对数据库表层级的数据进行锁定。具体以什么形式锁定,则要看具体的具体锁实现。
  由上图可知,表锁的具体实现有表级共享锁和表级排他锁。MyISAM下的共享锁和排他锁
  我们知道MyISAM存储引擎只支持在表层级对数据进行锁定,既只支持表锁。那么表层级具体的加锁实现有什么?既表级共享锁和表级排他锁表共享读锁(表级共享锁)
  获得表共享读锁的事务可以读取该表的任意数据。MyISAM引擎在执行select语句前,会自动给涉及的表加表共享读锁表独占写锁(表级排他锁)
  获得表独占写锁的事务可以更新或删除该表中任意数据。在执行update,delete,insert等语句前,会自动给涉及的表加表独占写锁
  只是很多场合更喜欢把表级共享锁和表级排他锁叫做表共享读锁和表独占写锁,实际上它们的意思是一样的表共享读锁和表独占写锁的兼容性
  既MyISAM的表锁可以做到,读读共享,读写互斥,写写互斥的功能读读共享:事务A获得表读锁,事务B依然可以获得表读锁读写互斥:事务A获得表读锁,事务B申请该表写锁则会阻塞,因为事务A获得了该表读锁,有互斥性写写互斥:事务A获得表写锁,事务B申请该表写锁则会阻塞,因为事务A获得了该表写锁,也有互斥性
  值得注意的是TheLOCALmodifierenablesnonconflictingINSERTstatements(concurrentinserts)byothersessionstoexecutewhilethelockisheld。(SeeSection8。11。3,ConcurrentInserts。)However,READLOCALcannotbeusedifyouaregoingtomanipulatethedatabaseusingprocessesexternaltotheserverwhileyouholdthelock。ForInnoDBtables,READLOCAListhesameasREAD
  MyISAM在一定程度上还是可以支持并发的进行查询和插入操作的。既如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个线程读表的同时,另一个线程从表尾插入记录。这属于MyISAM的特性,所以InnoDB存储引擎是不支持的!总结
  虽然MySQL支持表,页,行三级锁定,但MyISAM存储引擎只支持表级的数据锁定,既表锁。所以MyISAM的加锁相对比较开销低,但数据操作的并发性能相对就不高。但如果写操作都是尾插入,那么还是可以支持一定程度的读写并发
  既MyISAM的数据操作如果导致加锁行为,那么该锁肯定是一个表锁,会对全表数据进行加锁。但也要看具体什么形式的表锁,不同形式的表锁有着不同的特性
  同时从MyISAM所支持的锁中也可以看出,MyISAM是一个支持读读并发,但不支持通用读写并发,写写并发的数据库引擎,所以它更适合用于读多写少的应用场合InnoDB引擎所支持的锁官方列举的InnoDB引擎的锁
  我们从图中大概可以看出这么几种锁:共享锁和排他锁(SharedandExclusiveLocks)意向锁(IntentionLocks)记录锁(RecordLocks)间隙锁(GapLocks)临键锁(NextKeyLocks)插入意向锁(InsertIntentionLocks)主键自增锁(AUTOINCLocks)空间索引断言锁(PredicateLocksforSpatialIndexes)
  为了避免陷入名词混乱的漩涡,我们这里这说明重点,并不讲主键自增锁,空间索引断言锁之类的锁
  InnoDB下的表锁和行锁表锁和行锁
  InnoDB存储引擎,不仅仅支持表级锁定,还支持行级锁定。说白了就是不仅支持表锁,还支持MyISAM所不支持的行锁。表锁,行锁并不是一个真正的锁,只是代表可以对数据库对应层级的数据进行锁定。具体以什么形式去锁定,则要看具体的具体锁实现而表锁具体的锁实现则有共享锁,排他锁,意向锁等。而行锁则有共享锁和排他锁,另外行锁本身还有记录锁,间隙锁和临键锁的不同算法实现。那是不是行级锁一定比表级锁要好呢?那到未必,锁的粒度越细,代价越高,相比表级锁在表的头部直接加锁,行级锁还要扫描找到对应的行对其上锁,这样的代价其实是比较高的总之,锁的粒度越细,需要实现的开销越大,所以表锁和行锁各有好处表锁和行锁的分类
  因为我们知道,表锁和行锁并不是一把具体的锁,仅仅代表要在数据库的那个层次结构对数据进行锁定,这也代表了表,行锁还可以被细化出一下具体的锁实现
  InnoDB实现的行锁
  InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁的实现也意味着,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!InnoDB存储引擎的表在不使用索引时使用表锁有了索引以后,在对索引字段查询时,使用的就是行级锁由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,还是会出现锁冲突的,因为他们使用的是同一把锁当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁InnoDB下的共享锁和排他锁什么是共享锁和排他锁?共享锁(SharedLock),既S锁,又称读锁。
  事务拿到某一行记录的S锁,才可以读取这一行的数据。共享锁可以实现读读共享,读写互斥排他锁(ExclusiveLock),既X锁,又称写锁,独占锁。
  事务拿到某一行记录的X锁,才可以修改或者删除这一行的数据。排他锁可以实现读写互斥,写写互斥表行层次下的共享锁和排他锁
  因为InnoDB支持表锁和行锁。所以在数据库层次结构的表级和行级,都可以对数据进行锁定,具体以什么方式进行锁定呢?共享锁和排他锁就是本节要讨论的具体锁实现表级共享锁
  表级共享锁,又称为表共享读锁,既在表的层级上对数据加以共享锁,实现读读共享表级排他锁
  表级排他锁,又称为表独占写锁,既在表的层级上对数据加以排他锁,实现读写互斥,写写互斥行级共享锁
  行级共享锁既在行的层级上,对数据加以共享锁,实现对该行数据的读读共享行级排他锁
  行级排他锁既在行的层级上,对数据加以排他锁,实现对该行数据的读写互斥,写写互斥共享锁和排它锁的兼容性
  多个事务可以拿到一把S锁,可以实现读读共享而只有一个事务可以拿到X锁,可以实现读写互斥,写写互斥
  一句话,就是读读共享,读写互斥,写写互斥。这里要理解一个概念,上表仅仅是同一层次的共享锁和排他锁之间的兼容性,并非是表锁和行锁共存的情况。怎么显式地加共享锁或排他锁?selectfromtablelockinsharemode为table的所有数据加上共享锁,既表级共享锁selectfromtableforupdate为table的所有数据加上排他锁,既表级排他锁selectfromtablewhereid1forupdate为table中id为1的那行数据加上排他锁,既行级排他锁selectfromtablewhereid1lockinsharemode为table中id为1的那行数据加上共享锁,既行级共享锁
  当然以上,加的是行锁的前提是,id为主键且在查询命中,否则行锁会轮为表锁InnoDB下的意向锁为什么会有意向锁?InnoDBsupportsmultiplegranularitylockingwhichpermitscoexistenceofrowlocksandtablelocks。Forexample,astatementsuchasLOCKTABLESWRITEtakesanexclusivelock(anXlock)onthespecifiedtable。Tomakelockingatmultiplegranularitylevelspractical,InnoDBusesintentionlocks。Intentionlocksaretablelevellocksthatindicatewhichtypeoflock(sharedorexclusive)atransactionrequireslaterforarowinatable
  既通常情况下,表锁和行锁是相互冲突的,既获得了表锁,就无法再获得该表具体行的行锁,反之亦然。但是有的时候表锁和行锁实现部分的共存有利于更细粒度的对锁进行控制,以便得到更加的并发性能。所以InnoDB存储引擎支持多粒度(granular)锁定,这种锁定允许一个事务中同时存在行锁和表锁。
  所以InnoDB为了实现行锁和表锁共存的多粒度锁机制特性,InnoDB存储引擎也就还支持一种额外的锁方式以对多粒度锁机制进行支持,称之为意向锁(IntentionLock)。什么是意向锁呢?意向锁(IntentionLock)就是一种不与行级锁冲突的表级锁(重点!!)意向锁的主要目的展示出某事务已对表中某行加锁,或即将对表中某行加锁意向锁就是指,未来的某个时刻,事务可能要对某行加共享锁或排它锁了,先提前声明一个意向
  并且意向锁具体实现又可以分为以下两种:意向共享锁(intentionsharedlock,IS)
  事务打算给表中的某些行加行级共享锁,事务在给某些行加S锁前必须先取得该表的IS锁。意向排他锁(intentionexclusivelock,IX)
  事务打算给表中的某些加行级排他锁,事务在给某些行加X锁前必须先取得该表的IX锁。
  总之所谓意向锁,就是提前表明了一个要加行锁的意向。当某表存在排他意向锁时,代表该表的某行可能存在行级排他锁。同理当某表存在共享意向锁时,代表该表的某行可能存在行级共享锁意向锁的兼容性
  意向锁是一个比较弱的锁,所以意向锁之间互不排斥
  意向锁因为是表级的锁,本身就是为了解决行表锁的共存,所以它是不会与行锁产生冲突的。所以上表的兼容性指代的是意向锁和表级共享锁,表级排他锁的兼容性。怎么使用意向锁?意向锁的维护是由存储引擎隐式帮我们做了,不需要程序员操心!既意向锁是由存储引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享排他锁之前,InooDB会先获取该数据行所在的表的对应意向锁InnoDB下的记录锁,间隙锁,临键锁
  我们的行锁根据锁的粗细粒度又可以分为三种锁,既记录锁,间隙锁和临键锁
  什么是记录锁?
  记录锁(RecordLock)就是我们最单纯认知的行锁,既只锁住一条行记录,准确的说是一条索引记录。
  InnoDB的行锁是依赖索引实现的,而其锁住某行数据的本质是锁住行数据对应在聚簇索引的索引记录。例如某个事务执行了selectfromtwhereid1forupdate;语句,就相当于它会在id1的索引记录上加上一把锁,以阻止其他事务插入,更新,删除id1的这一行。
  此行锁非彼行锁
  通常字面意思的行锁,代表对一行记录加锁。但行锁实际是一个抽象,我们平时所说行锁(1)还分记录锁,间隙锁(GapLock),临键锁(NextKeyLock)等具体的实现,但我们通常意义上单纯的行锁(2),实际说的就是记录锁;既此行锁(1)非彼行锁(2),行锁(1)更倾向是一个锁分类,代指一系列行锁。行锁(2)更接地气,更单纯,就是指锁单条记录的意思,随意不同场景,不同语义下,所代表的意思可能有些许不同;但通常情况下,都会被混在一起,所以也不用太介意,自己要清楚就好什么是间隙锁?
  间隙锁(GapLock),顾名思义,它会封锁索引记录中的缝隙,不让其他事务在缝隙中插入数据。它锁定的是一个不包含索引本身的开区间范围(index1,index2)。间隙锁是封锁索引记录之间的间隙,或者封锁第一条索引记录之前的范围,又或者最后一条索引记录之后的范围
  说白了,间隙锁的目的就是为了防止索引间隔被其他事务的插入。间隙锁是InnoDB权衡性能和并发性后出来的特性。
  间隙锁之间是互相兼容的,既不同事务的Gap锁是可以共存的,可以存在重合区域或是完全重合。多个事务的Gap锁重合代表多个事务都想阻止其他事务往该索引间隙插入数据。也因为Gap一次就对插入行为锁住了一片的区域,不利于多事务并发写。所以后续MySQL也就提供了一种特殊的间隙锁(插入意向锁),以解决并发写的问题
  间隙锁实际也分共享间隙锁,排他间隙锁,虽然有分类,但事实上他们的意义是等价毫无区别的,所以可以忽略这一层,只要知道它们的作用都是阻止其他事务往间隙插入数据。
  间隙锁只发生在事务隔离级别为RR(RepeatableRead)的情况下,它用于在隔离级别为RR时,阻止幻读(phantomrow)的发生;隔离级别为RC时,搜索和索引扫描时,Gap锁是被禁用的,只在外键约束检查和重复key检查时Gap锁才有效,正是因为此,RC时会幻读问题。
  比如某个事务执行selectfromtablewhereidbetween10and20forupdate;语句,当其他事务往表里插入id在(10,20)之间的值时,就会被(10,20)的间隙锁给阻塞什么是临键锁?
  临键锁(NextKeyLock)其实并不能算是一把新的行锁,其实际就是记录锁(RecordLock)和间隙锁(GapLock)的组合,既封锁了缝隙,又封锁了索引本身,既组合起来构成了一个半开闭区间的锁范围。既临键锁锁的是索引记录本身,以及索引记录之前的间隙(index1,index2)
  比如某表有4行数据,主键分别为10,11,13,20。那么该表可能存在的临键锁锁住聚簇索引的区间如下(negativeinfinity,10〕(10,11〕(11,13〕(13,20〕(20,positiveinfinity)
  每两个索引项之间就是一个nextkey锁区域,通常规则是左开右闭,除了最后一个锁区间,是全开区间,代表锁住索引最大项之后的区域记录锁,间隙锁,临键锁的关系
  我们知道InnoDB的行锁默认是基于BTree的。所以行锁依赖的索引是有序的。记录锁就是单纯意义上的行锁,锁的就是单行数据,该数据是真实存在的而间隙锁则是锁住一个区间中多行数据,但这些多行的数据实际是并不存在的。既只锁住真实数据对应索引项之间的一个空间范围而临键锁说白了就是记录锁间隙锁的组合。只要把记录锁和间隙锁组合在一起,就是临键锁,既锁住索引项本身的真实数据,又锁住两两索引之间没有数据的空间范围。排他,共享锁与记录锁,间隙锁,临键锁的关系
  的确,我们一直都说行锁是一个抽象,只代表在行层级对数据进行锁定。我们也说行锁实际有具体的实现,比如排他锁和共享锁。为什么这个时候又冒出了一些记录锁,间隙锁,临键锁的概念?!这是在懵我读书少吗?
  其实排他锁,共享锁与记录锁,间隙锁,临键锁本不应该混淆在一起的,因为他们虽然都属于行锁的范畴,但却是不同维度(角度)的概念。排他锁和共享锁的概念,注重是从行锁的功能性角度分类,强调的是这把行锁,允不允许被其他事务所共享,更像是描述该锁的功能模式特性记录锁等概念,注重的是从行锁的锁粒度角度分类,强调的是这把行锁,锁的是单行,还是锁的一个行区间范围,更像是描述这把锁的锁范围
  所以它们只是不同角度分类下的概念,比如我们可以这么认为,如果一把行锁在锁粒度上的实现是一个记录锁,那么该行锁就是一把记录锁,而这个记录锁在功能上的实现是一把共享锁,那么这把记录锁就是一把共享锁。在这个角度上分析,此时这把行锁即是记录锁,也是共享锁。InnoDB下的插入意向锁什么是插入意向锁?
  之前,我们学习了什么是意向锁,IS,IX的其中一个好处是兼容行级S锁和表级S锁,做到真正的读读共享。那什么是插入意向锁呢?插入意向锁一种特殊的间隙锁,属于行锁。其实插入意向锁的好处也类似,但要做到的功能并非读读共享,而是针对某个区间范围做到写写共享,但这个写写并非对同一行记录而言,而是针对某个区间范围内的写入可以并发执行,只要写入的并非同一索引项(行)。
  说白了,就是插入意向锁允许多个事务的插入写操作在某个索引区间无需等待的并发执行,只要操作的不是同一行的数据插入意向锁和意向锁的关系可以说是完全没有关系,唯一的关系最多都表名一个意向。虽然插入意向锁也表示插入的意向,但是它跟IX,IS是完全不一样的。另外意向锁(IS,IX)是表级锁,而插入意向锁实际是行级锁插入意向锁并不属于意向锁,而实际是一种特殊的间隙锁插入意向锁和Gap锁的关系
  相同点插入意向锁是一种特殊的Gap锁,而原Gap锁相对而言就是普通的Gap锁插入意向锁和普通Gap锁针对S,X的分类,都一样,都是属于等价的,所以对Gap锁而言,S,X的分类是没有意义的。插入意向锁和普通Gap锁都对彼此相互不兼容。既插入意向锁锁的间隙和普通Gap锁锁的间隙不同有重合,否则会阻塞
  不同点普通Gap锁的目的是为了防止其他事务对锁间隙的插入行为。作用之一就是避免了在RR级别下幻读行为而插入意向锁的目的是替换插入行为产生的普通Gap锁(因为普通Gap锁不支持多事物对同一间隙进行插入),其中最大的作用是允许多事务在锁间隙内并发写入插入意向锁兼容性
  以下我们来说说插入意向锁的兼容性
  因为插入意向锁是特殊的Gap锁,锁的也是间隙,所以插入意向锁不与记录锁有任何冲突,因为一个锁的是索引,一个锁的是索引之间的间隙。插入意向锁跟临键锁的兼容就跟Gap锁一样,因为临键锁的组成部分就有Gap锁插入意向锁和插入意向锁之间是相互兼容的,普通Gap锁与普通Gap锁之间也是相互兼容的。但是插入意向锁和Gap却是不兼容的。既如何某个事务A先获得了一个Gap锁,事务B插入新行,获得了插入意向锁。如果两者之间的间隙有重合,那么事务B的插入意向锁则会被事务A的Gap锁阻塞插入意向锁的作用?以及为何替代Gap锁
  我们已经知道了插入间隙锁最主要的作用就是站在多事务操作的不是同一行数据的基础上,可以让某个索引区间范围做到并发的插入写操作。那么为什么又拿插入意向锁这种特殊的Gap锁去代替普通Gap锁呢?这是有什么独特之处吗?
  1。在了解插入意向锁作用之前,你得明白事务的插入行为会造成什么?
  我们肯定简单的知道,当某个事务插入一个新行时,肯定要获取对该行的排他记录锁。看上去好像没有毛病。问题是,在新行没有生产前,怎么获取对该新行的排他记录锁?明显就不能嘛,所以一个插入行为,在获取对新行的排他记录锁之前,我们需要先获取新行所在的索引区间的锁,既间隙锁。
  既一个插入单行数据的行为,必须先获得一个粗粒度的锁,才能安全的保证新行生成前,没有其他事务插入同样的新行(避免冲突)。
  间隙锁在这里的作用就是阻塞企图在该索引间隙中插入数据的其他事务。
  2。所以我们明白了,一个插入行为,必须要先获得粗粒度的间隙锁,才能保证生成新行,再获取细粒度该行的排他记录锁。但是因为普通的Gap锁一旦锁住了某个间隙,这个间隙就不再允许其他事务插入数据了。既其他事务需要等待当前事务释放该区间的Gap锁后,才能插入数据。所以我们可以知道,因为Gap锁对插入行为的相对锁粒度比较大,就不利于提高多事务对同一个索引间隙的数据插入性能了。说白了就是普通Gap锁一次就锁一个区间,如果多事务比如成多线程,那么这些多线程在执行Gap锁间隙的插入行为就是同步的。而插入意向锁就不一样了,插入意向锁虽然跟Gap锁一样,一次锁的是一个区间。但是它可以允许多个事务在这个区间内执行不同数据的插入,互不干扰。举个小例子,如果一张表有两行记录,主键是1和10,此时有5个并发事务准备在(1,10)区间内插入5条不同主键的数据,每次插入需要1s的时间消耗。如果插入行为提前获取的粗粒度锁是普通Gap锁,那么耗时就是5s,如果是插入意向锁,那就是1s。这个时间开销显而易见
  综上,在插入行为方面,Gap锁在这方面的功能最终是被插入意向锁所代替的,插入意向锁就是为了改善Gap锁在数据插入方面的同步开销而引入的特殊Gap锁乐观锁和悲观锁无论是悲观锁还是乐观锁,他们本质上不是数据库中具体的锁概念,而是我们定义出来,用来描述两种类别的锁的思想。所以有了设计的分类,我们就可以通过这个分类去对数据库中具体的锁进行分门别类;不过数据库中的乐观锁更倾向叫乐观并发控制(OCC),悲观锁叫悲观并发控制(PCC),还有区别于乐观悲观锁的一种控制叫MVCC,多版本并发控制也不要把乐观锁和悲观锁与数据库中的行锁,表锁,排他锁,共享锁混为一谈,他们并不是一个维度的东西;前者是一个锁思想,可以将后者根据是否进行趋近于乐观或悲观锁的思想进行分类乐观锁和悲观锁的概念不仅仅存在于数据库领域,可以说存在线程安全,存在并发的场景几乎都有乐观锁和悲观锁的适用场景,比如Java中也有乐观锁和悲观锁思想的具体实现;但不同领域的乐观和悲观锁的具体实现都不尽相同,要解决的问题也可能有所不一样
  所以要是别人再问你乐观锁和悲观锁是什么,你千万别说它是一种具体的锁,它只是一种锁的设计思想,他可以有很多具体的实现类悲观锁什么是悲观锁?
  在关系数据库管理系统里,悲观并发控制(又名悲观锁,PessimisticConcurrencyControl,缩写PCC)是一种并发控制的方法;悲观锁指的是采用一种持悲观消极的态度,默认数据被外界访问时,必然会产生冲突,所以在数据处理的整个过程中都采用加锁的状态,保证同一时间,只有一个线程可以访问到数据,实现数据的排他性;通常,数据库的悲观锁是利用数据库本身提供的锁机制去实现的。
  数据库的悲观并发控制可以解决读写冲突和写写冲突,指在用加锁的方式去解决悲观锁的实现
  通常情况下,数据库的悲观锁就是利用数据库本身提供的锁去实现的外界要访问某条数据,那它就要首先向数据库申请该数据的锁(某种锁)如果获得成功,那它就可以操作该数据,在它操作期间,其他客户端就无法再操作该数据了如果获得失败,则代表同一时间已有其他客户端获得了该锁,那就必须等待其他客户端释放锁
  当然数据库提供了非常多的锁,每种数据库提供的锁也不尽然相同,所以具体情况就要看是什么锁了,比如行锁,表锁等优点与缺点
  悲观并发控制实际上是先取锁再访问的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;另外,在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数
  优点:适合在写多读少的并发环境中使用,虽然无法维持非常高的性能,但是在乐观锁无法提更好的性能前提下,可以做到数据的安全性
  缺点:加锁会增加系统开销,虽然能保证数据的安全,但数据处理吞吐量低,不适合在读书写少的场合下使用乐观锁什么是乐观锁?
  在关系数据库管理系统里,乐观并发控制(又名乐观锁,OptimisticConcurrencyControl,缩写OCC)是一种并发控制的方法;乐观锁(OptimisticLocking)是相对悲观锁而言,乐观锁是假设认为即使在并发环境中,外界对数据的操作一般是不会造成冲突,所以并不会去加锁(所以乐观锁不是一把锁),而是在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回冲突信息,让用户决定如何去做下一步,比如说重试,直至成功为止;数据库的乐观锁,并不是利用数据库本身的锁去实现的,可能是利用某种实现逻辑去实现做到乐观锁的思想
  数据库的乐观并发控制要解决的是数据库并发场景下的写写冲突,指在用无锁的方式去解决CAS思想
  其实数据库乐观锁的具体实现几乎就跟Java中乐观锁采用的CAS算法思想是一致,所以我们可以从CAS算法中学习到数据库乐观锁的设计:
  CAS指令全称为CompareandSwap,它是系统的指令集,整个CAS操作是一个原子操作,是不可分割的。从具体的描述上,我们可以这么看CAS操作:
  CAS指令需要3个操作数,分别是内存位置V,旧的预期值A,和新值B。CAS指令执行时,当我们读取的内置位置V的现值等于旧预期值A时,处理器才会将新值B去更新内置位置V的值。否则它就不执行更新,但无论是否更新V的值,都会返回V的旧值。
  我们通俗的放到代码层次上去理解i2;i,就是说:首先线程1从内存位置V中读取到了值,保存并作为旧预期值A。(v2,a2)然后在因为i要进行操作,系统会比较内存位置V的现值跟旧预期值A进行比较,既V?A。如果相等,Bi3,新值B就会对内存位置V进行更新,所以内存位置V的值就变成了B的值,3如果不相等,则说明有其他的线程修改过了内存位置V的值,比如线程2在线程1修改i的值前就更新了i的值。,所以线程1会更新变量i失败。但线程不会挂起,而是返回失败状态,等待调用线程决定是否重试或其他操作。(通常会重试直到成功)
  数据库层的乐观锁实现也类似代码层面的实现。数据库中乐观锁的实现
  通常乐观锁的实现有两种,但它们的内在都是CAS思想的设计:
  方式一:使用数据版本(version)实现这是乐观锁最常用的一种实现方式。什么是数据版本呢?就是在表中增添一个字段作为该记录的版本标识,比如叫version,每次对该记录的写操作都会让version1。所以当我们读取了数据(包括version),做出更新,要提交的时候,就会拿取得的version去跟数据库中的version比较是否一致,如果一致则代表这个时间段,并没有其他的线程的也修改过这个数据,给予更新,同时version1;如果不一致,则代表在这个时间段,该记录以及被其他线程修改过了,认为是过期数据,返回冲突信息,让用户决定下一步动作,比如重试(重新读取最新数据,再过更新)updatetablesetnumnum1,versionversion1whereversion{version}andid{id}
  方式二:使用时间戳(timestamp)实现表中增加一个字段,名称无所谓,比如叫updatetime,字段类型使用时间戳(timestamp)原理和方式一一致,也是在更新提交的时检查当前数据库中数据的时间戳和自己更新前取到的时间戳是否一致,如果一致则代表此刻没有冲突,可以提交更新,同时时间戳更新为当前时间,否则就是该时间段有其他线程也更新提交过,返回冲突信息,等待用户下一步动作。updatetablesetnumnum1,updatetimeunixtimestamp(now())whereid{id}andupdatetime{updateTime}
  但是我们要注意的是,要实现乐观锁的思想的同时,我们必须要要保证CAS多个操作的原子性,即获取数据库数据的版本,拿数据库的数据版本与之前拿到的版本的比较,以及更新数据等这几个操作的执行必须是连贯执行,具有复合操作的原子性;所以如果是数据库的SQL,那么我们就要保证多个SQL操作处于同一个事务中优点与缺点
  优点:
  在读多写少的并发场景下,可以避免数据库加锁的开销,提高Dao层的响应性能
  其实很多情况下,我们orm工具都有带有乐观锁的实现,所以这些方法不一定需要我们人为的去实现
  缺点:
  在写多读少的并发场景下,即在写操作竞争激烈的情况下,会导致CAS多次重试,冲突频率过高,导致开销比悲观锁更高乐观锁和悲观锁的抉择
  对乐观锁和悲观锁的抉择主要体现在写写
  在悲观锁和乐观锁的抉择中,我们可以从下面三个因素来考虑:响应速度:如果Dao层需要非常高的响应速度,尤其是读多写少的场景下,那我们就可以采用乐观锁方案,降低数据库锁的开销,提供并发量冲突频率:如果冲突频率非常高,那么我们就可以采用悲观锁,保证成功率;毕竟如果冲突频率大,乐观锁会需要多次重试才能成功,代价可能会大大增加重试代价:如果重试代价大,比如说重试过程的代码执行非常耗时,那么此时我就不建议使用乐观锁了,还不如直接上悲观锁来了爽快
  所以我们知道:在读多写少,CAS竞争没这么激烈的时候,我们可以采用乐观锁策略,降低数据库加锁的开销,提高数据库并发响应在写多读少的场景下,因为会产生大量的CAS竞争,且重试成本比较高的情况下,我们就不建议再采用乐观锁策略了,还是直接使用悲观锁的数据库加锁吧OCC,PCC,MVCC三者的关系悲观并发控制(PCC)是一种用来解决读写冲突和写写冲突的的加锁并发控制,为每个操作都加锁,同一时间下,只有获得该锁的事务才能有权利对该数据进行操作,没有获得锁的事务只能等待其他事务释放锁;所以可以解决脏读,幻读,不可重复读,第一类更新丢失,第二类更新丢失的问题。乐观并发控制(OCC)是一种用来解决写写冲突的无锁并发控制,认为事务间争用没有那么多,所以先进行修改,在提交事务前,检查一下事务开始后,有没有新提交改变,如果没有就提交,如果有就放弃并重试。乐观并发控制类似自旋锁。乐观并发控制适用于低数据争用,写冲突比较少的环境;无法解决脏读,幻读,不可重复读,但是可以解决更新丢失问题。多版本并发控制(MVCC)是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。这样在读操作时就不用阻塞写操作,写操作也不用阻塞读操作;不仅可以提高并发性能,还可以解决脏读,幻读,不可重复读等事务问题。更新丢失问题除外。
  来源:https:blog。csdn。netSnailMannarticledetails88353099

如果中国出了一位像大阪直美一样的冠军,不像中国人,不会中国话,却代表中国夺冠了,你会骄傲吗?加拿大选手麦克尼尔100米蝶泳夺冠,她却是一副东方面孔,韩国短道速滑队长林孝俊入籍一事众说纷纭,试想一下,如果林孝俊代表中国取得了冬奥会短道速滑的冠军,那么我们会为之骄傲吗?其实对法院能查到被执行人所有银行卡账户吗,包括香港或者海外的银行吗?香港和国外的肯定查不到,但如果此人在香港或海外开户时用的是中国护照,那么国税局就会有此人在香港或海外的金融资产信息,包括存款股票和债券等信息。当然不能。任何法院,以前都只能在自己辖请问五大行总行进去后几年能摸到年薪50万?五大行属于国企,在2012年前,工资待遇没有明确标准,由行里根据经营情况自定,上不封顶,五大行的工资待遇可以说是相当高。特别是在总行,干到中层正职以上动辄几十万上百万,屡见不鲜。国有没有宝宝凌晨12点了还不睡觉的,宝妈什么心情?这个我太有发言权了!宝宝这样的状态已持续半个月了,从无奈到崩溃,再到现在的慢慢适应,真的是欲哭无泪啊!基本每晚都在12点以后,有时甚至一两点。原来,还有这样的宝宝存在啊,我还以为只你给宝宝用过最差的纸尿裤是什么品牌的?差评原因是什么?帮宝适,真的是想直接扔了,发现评论区也是帮宝适高票当选。孕期逛会展中心集了各种纸尿裤试用装,觉得露安适是最柔软的,米菲最薄的,但是宝宝没出生时候也没办法测试哪个用着更好。后来宝宝早DNF为什么很多天帝玩家传说勋章带着30魔攻48智力的属性,不应该是带30独立48智力吗?DNF传说勋章是伤害提升最重要的的细节打造,在附魔了7属强之后大约能给角色带来23的提升,对于目前来说由于公会的改版以及活动的赠送,拥有一个传说勋章已经不再像已前这么困难了,不过对神舟笔记本战神系列怎么样?神舟战神现在还是很不错的。(正文较长,会普及一些神舟战神内部的模具知识,难免会枯燥,请大家理解,谢谢)神舟战神系列笔记本,一直都是神舟笔记本销售的主力军。之所以有很多人黑神舟战神,为什么知乎上的很多大学生都是穿的zara优衣库,现实中却有很多都不知道这些牌子的大学生?不要信知乎,以前知乎是个探讨知识的地方,现在不是了,知道现在知乎的别名是什么?逼乎就是一个装逼的地方!人人年薪百万,个个帅哥美女,出国留学回来的,都网络地球村了,你信么,现在国家统滴滴在纽交所低调上市,高调退市,究竟有没有把数据给美国?滴D在美丽国纽交所上市确实是非常低调,低调到让人没法理解。按照这些天司马先生在一期视频里的说法,滴D连上市的钟都没敲。对于任何一家公司来说,IPO上市都是具有里程碑意义的,都是要大三本和二本都是本科,为什么大家更愿意上二本?大学本科按照民间的分法,有一本二本和三本之分。能够被一本录取当然是多数大学生喜闻乐见的事情。但是被三本录取,很多人宁愿复读也不愿念三本,甚至不念书也不去念三本。原因大概有以下四种。在西安工作管吃住六千元,可以干吗?在西安工作管吃住六千,是可以干的。西安平均工资不高,有6000工资算是可以呢从上面这份图表可以看出,很大部分的工资是在20003000元,这部分人占还是挺多。所以在西安有6000元
S12最精彩BO1诞生!JDG完美团战干碎DK,牙膏沙皇一战成名哈喽大家好,这里是狗子,每天为您带来有趣的游戏资讯,喜欢的记得点个关注S12全球总决赛第二日的比赛已经全部结束了,在这两日的小组赛程当中,除了EDG第一日输给了T1之外,其他5场比S12小组赛第二日LPL三战全胜EDG战胜C9TES轻取GAMJDG力克DK昨日LCK解说在GEG比赛前说到现在没输过,好想尝尝输的滋味啊,结果今天小组赛比赛第二日LCK全军覆没,至此LCK已经4连败,从一号种子输到4号种子。网友热议LCK明显在布局s13S12小组赛LPL上单巡礼从2012年接触英雄联盟开始,就一直喜欢玩上单,所以也一直喜欢上单选手。在S8决赛IG对战G2上,解说记得说了一句经典的话天不生theshy,LPL上单万古如长夜!说的有点夸张,但除掉最大心病阵容深度可观,四强是山东男篮的基本目标?季前赛两连胜为山东男篮本赛季的征程拉开了一个不错的序幕,北京时间10月10日,CBA联赛正式拉开大幕,可以说山东男篮是正八经的揭幕战,他们将面对实力不俗的深圳男篮。说起来,山东男篮先败于巴西,后败于意大利,女排天花板已现,需尽快考虑重整队伍任何运动,都是需要资质与天赋的。若先天不足,后天怎么努力弥补,都不足以成就伟业。就像艾格努只能是艾格努,其他人无法成为她,朱婷只能是朱婷。而由蔡斌领导的这支中国女排,也只能是一支世在希望的田野上从高产向高质转变山西绛县10万亩山楂迎丰收央视网消息日前,山西省运城市绛县的10万亩山楂陆续迎来丰收,红彤彤的山楂挂满枝头,果农们忙着采摘,现场一派丰收的景象。在山西省绛县郑柴村万亩山楂种植基地,一串串成熟的山楂挂满了枝头张祖强开启气象服务高质量发展新征程瞭望开启气象服务高质量发展新征程张祖强气象服务必须紧贴国家和人民需求,全面融入经济社会发展全局,全方位服务保障社会主义现代化强国建设气象部门需要更加注重内外共生系统联动的融入式发展,更各方齐发力假期不歇脚稳经济再吹集结号证券时报记者孙璐璐贺觉渊秦燕玲刚刚结束的国庆长假,一些来自政府部门公共服务事业单位银行业金融机构等领域的从业者,一直忙碌在工作一线,以实际行动稳经济大盘,迎接二十大胜利召开。进入1首批公募REITs扩募!博时华安富国中金红土创新饮ampampquot头啖汤ampampquot继此前发布REITs扩募指引后,市场正式迎来了首批公募REITs扩募。记者从沪深两大交易所处获悉,截至10月8日,共有5只公募REITs提交了扩募申请,且相关申请均已成功受理。5只秋季更新预告四全新攻城机器与法术首领们,大家好!如果你还记得昨天的更新预告,最后那句话可能让人有听没有懂,但今天的更新预告将让你有听也能懂!就跟战宠小屋的新等级一样,法术工厂和攻城机器工坊的新等级也预示着全新单位1993年的马力欧真人电影,为什么是任天堂的黑历史?噔噔蹬噔噔蹬我不知道你有没有看凌晨四点的超级马力欧兄弟预告片。我反正看了,感觉还不错。小黄人团队做动画肯定没得说,星爵配音的妈妈咪呀还没出声,但想来不会太坏,至于游戏还原与否你瞧这
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网