《全局锁表级锁和行锁MySQL三种锁的原理和用途.docx》由会员分享,可在线阅读,更多相关《全局锁表级锁和行锁MySQL三种锁的原理和用途.docx(10页珍藏版)》请在第一文库网上搜索。
1、全局锁、表级锁和行锁MySQ1三种锁的原理和用途前言锁是服务器在协调多个进程/线程并发访问某一资源的访问机制。数据是一种用户共享的资源,保证数据并发访问的一致性、有效性是关系型数据库的本质问题,锁冲突同时也是也是影响数据库并发访问性能重要度量指标。要想学好关系型数据库,锁机制是DBA一个绕不开的话题。今天就讲一讲MySQ1的三种锁。根据加锁的范围,MySQ1里面的锁大致可以分成全局锁,表级锁,行锁;本文主要讲述MySQ1的这三种锁的原理和用途。一、全局锁MySQ1提供了一种加全局读锁的方法,命令是FIUShtab1eswithread1ock(FTWR1)o全局锁就是对整个数据库进行加锁。当你
2、需要让整个库处于只读状态的时候,可以使用这个命令,之后的其他线程的以下语句会被阻塞:数据DM1的更新操作(数据的增删改)、数据DD1的定义语句(包括建表、修改表结构等)和事务更新类的提交语句。1.1全局锁的应用场景全局锁的一个非常典型场景为:1、使用mysq1dump做全库逻辑备份;2、主库在做完全库逻辑备后在从库上做主从配置。使用mysq1dump做初始化工作。以前的常规做法是使用F1ushtab1eswithread1ock(FTWR1)锁全库,然后对整个库进行逻辑备份,命令如下:这种场景下会带来一定的局限性:1如在主库mysq1dump操作,备份期间数据库不能执行增删改,影响业务正常使用
3、,在备份时间长的情况下,此操作业务不可容忍;2.如在从库mysq1dump操作,那么备份期间从库不能执行主库同步过来的bin1og进行同步更新,导致主从延迟。可以在从库上执行如下命令,参考Seconds_Behind_Master,多刷几遍命令可以看到参数一直在增大。!注意:上述场景为不加一SingIeTranSaCtiOn参数的逻辑备。如果想不影响业务正常使用,则可使用如下命令:-sing1e-transaction的参数意义,可以使用命令进行查看那么,加全局锁如此不好,备份为什么要加锁呢?这是因为数据一致性的问题,如不加全局锁的话,备份发起时库的数据一致性和恢复后的数据库一致性不在一个逻辑
4、时间点,会导致备份数据库和恢复数据库的数据逻辑不一致的。为什么需要全局读锁(FTwR1)官方自带的逻辑备份工具是mysq1dumpo当mysq1dump使用参数一sing1etransaction的时候,导数据之前就会启动一个事务,来确保拿到一致性快照视图。由于MVCC的支持,备份库期间数据是可以正常更新的。MVCC是个嘛?MVCC(Mu1ti-VersionConcurrencyContro1|多版本并发控制)InnoDB通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时
5、的实际时间,相反它只存储这些事件发生时的系统版本号(1SN)o这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。MVCC对普通的SE1ECT不加锁,直接利用MVCC读取指版本的值,避免了对数据重复加锁的过程。UndoIog是InnodbMVCC重要组成部分,InnODB的MVCC就是基于UndOIog实现的。InnODB支持MVeC多版本,其中RC和RR隔离级别是利用COnSiStentreadVieW方式支持的,即在某个时刻对事物系统打快照记下所有活跃读写事务ID,之后读操作根据事务ID与快照中的事
6、务ID进行比较,判断可见性。综上,MVCC的实现,通过保存数据在某个时间点的快照来实现的。意味着一个事务无论运行多长时间,在同一个事务里能够看到数据一致的视图。根据事务开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据可能是不同的。为什么还需要FTWR1?sing1e-transaction方法只适用于使用InnOdb引擎的库。如果有的表使用了不支持事务的引擎,那么备份就只能通过FTWR1方法。比如,对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。所以,就需要使用FTWR1命令保持非I1modb的一致性读。这也是D
7、BA要求业务开发人员使用InnoDB替代MyISAM的原因之一。二、表级锁MySQ1表级锁有两种:一是表锁,一是元数据锁2.1表锁表锁的语法是1ocktab1esread/write,示例如下:表锁与FTWR1类似,可用un1ocktab1es主动释放锁,客户端断开时也会自动释放。注意:IoCktab1es语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。在还没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式。而对于InnoDB这种支持行锁的引擎,一般不使用1ocktab1es命令来控制并发,毕竟锁住整个表的影响面还是太大了。2.2MD1锁另一类表级锁是MD1(metada
8、ta1ock)oMySQ15.5版本中引入了MD1,MD1不需要显式使用,当对一个表做增删改查操作和对表做结构变更操作时候,数据库会自动加上MD1。读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。虽然MD1锁是系统默认会加的,但却不能忽略的一个机制。比如在给一个小表添加个字段,缺导致整个数据库长时间业务不可用。为什么?以下为一个简单场景解释:在读取Cthan_tabIe时,SeSSiOn1对表做了一个MD1读锁,到了SeSSiOn2也对etha
9、n_tab1e加了一个MD1读锁;这时session1和session2均可以正常操作;之后session3需要MD1写锁,会被b1ocked,是因为sessionA的MD1读锁还没有释放,因此只能被阻塞。如果只有session3自己被阻塞还好,但是之后所有要在表ethan_tab1e上新申请MD1读锁的请求也会被sessionC3阻塞。而所有对表的增删改查操作均需先申请MD1读锁,因此后续的此类操作都被锁住,业务上来看就感觉此时这个库完全不可读写/不可用了。事务中的MD1锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。若ethan_tab1e表上的查询频
10、繁,且客户端有重试机制,超时后会再起一个新SeSSiOn请求,一段时间后数据库库的线程很快爆满,新发起的连接不能成功,业务表象是数据库完全不可用。划重点:行锁都有锁超时设定。但MD1锁没有超时限制,只要事务没提交就会一直锁。所以,在对大表操作时,大家都会特别小心,但更新小表时,如发生此类现象,也要学会分析。那怎么分析?怎么解决MD1锁?出现MD1时,就需要提交或者回滚事务。首先要找到这个事务,怎么找?通过information_schema.innodb_trx查看事务的执行时间trx_started表示什么时候执行的这个事务。使用Shc)Wfu11process1ist;查看这个线程id,通
11、过其中host字段,到底是谁连接了数据库,进去COmmit/ro11backo如不是IoCaIhOSt环境,而是应用程序连接,可联系业务进行commit/ro11backki110如何正确的给小表加字段?如有库中有长事务,且不提交,则会一直占着MD1锁。使用MySQ1的information_schema库的innodb_trx表可查到当前执行中的事务。如做DD1操作的表有长事务在执行,首先考虑暂停DD1,或ki11掉这个长事务。这也是为什么需要在低峰期做dd1变更的原因。三、InnODB行锁InrIoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQ1与Orac1e不同,后者是通过在
12、数据块中对相应数据行加锁来实现的。InnODB这种行锁实现特点意味着:只有通过索引条件检索数据,InnODB才使用行级锁,否则,InnODB将使用表锁。InnoDB的锁定机制和Orac1e数据库有不少相似之处。InnODB的行级锁定同样分为两种类型,共享锁和排他锁,而在锁定机制的实现过程中为了让行级锁定和表级锁定共存,InnoDB也同样使用了意向锁(表级锁定)的概念,也就有了意向共享锁和意向排他锁这两种。这里本文只介绍概念,后续将进行相应实验验证。什么是共享锁和排他锁?当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁定着自己需要的资源的时候,自己可以再加一个共享锁,不过不能
13、加排他锁。但是,如果遇到自己需要锁定的资源已经被一个排他锁占有之后,则只能等待该锁定释放资源之后自己才能获取锁定资源并添加自己的锁定。而意向锁的作用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向锁。如果自己需要一个共享锁,那么就在表上面添加一个意向共享锁。而如果自己需要的是某行(或者某些行)上面添加一个排他锁的话,则先在表上面添加一个意向排他锁。意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。所以,可以说InnoDB的锁定模式实际上可以分为四种:共享锁(S),排他锁(X),意向共享锁(IS)和意
14、向排他锁(IX),我们可以通过以下表格来总结上面这四种所的共存逻辑关系:以下是一些注意事项:1 .在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。2 .MySQ1的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,会出现锁冲突。3 .当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁。4 .表创建了索引字段,但是否使用索引来检索数据由MySQ1通过判断不同执行计划的代价来决定的,了解OraC1eCBO机制读者可能更容易理解;如果My
15、SQ1认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnODB将使用表锁,而非行锁。结语1本文简单介绍了MySQ1的全局锁,表级锁,行锁三种锁;有些地方需要后续试验做验证;如有不清楚的地方,欢迎大家探讨;2. InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQ1与Orac1e不同,后者是通过在数据块中对相应数据行加锁来实现。InnODB这种行锁实现特点意味着:只有通过索引条件检索数据,IImoDB才使用行级锁,否则,IrmODB将使用表锁。3. MySQ1除了共享锁-排他锁,还有意向共享锁(IS)和意向排他锁(IX);意向锁是InnODB自动加的,不需用户干预。对于UPDATE、DE1ETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SE1ECT语句,InnoDB不会加任何锁。参考:https:/https:/juejin.impost5ce8eee45188253114078f2ahttps:/kemep/11065025.htm1https:/p7d050498d9dahttps:/b1og,