《全局锁、表级锁和行锁-MySQL三种锁的原理和用途.docx》由会员分享,可在线阅读,更多相关《全局锁、表级锁和行锁-MySQL三种锁的原理和用途.docx(10页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、全局锁、表级锁和行锁MySQL三种锁的原理和用途前言锁是服务器在协调多个进程/线程并发访问某一资源的访问机制。数据是一种用户共享的资源,保证数据并发访问的一致性、有效性是关系型数 据库的本质问题,锁冲突同时也是也是影响数据库并发访问性能重要度量指 标。要想学好关系型数据库,锁机制是DBA一个绕不开的话题。今天就讲一讲MySQL的三种锁。根据加锁的范围,MySQL里面的锁大致可以分 成全局锁,表级锁,行锁;本文主要讲述MySQL的这三种锁的原理和用途。一、全局锁MySQL提供了一种加全局读锁的方法,命令是Flush tables with read lock (FTWRL) o全局锁就是对整个数
2、据库进行加锁。当你需要让整个库处于只读状态 的时候,可以使用这个命令,之后的其他线程的以下语句会被阻塞:数据DML3 .当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另 外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数 据加锁。4 .表创建了索引字段,但是否使用索引来检索数据由MySQL通过判断不同执行 计划的代价来决定的,了解Oracle CB0机制读者可能更容易理解;如果MySQL 认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况 下InnoDB将使用表锁,而非行锁。结语本文简单介绍了 MySQL的全局锁,表级锁,行锁三种锁;
3、有些地方需要后续 试验做验证;如有不清楚的地方,欢迎大家探讨;1. InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle 不同,后者是通过在数据块中对相应数据行加锁来实现。InnoDB这种行锁实现 特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则, InnoDB将使用表锁。2. MySQL除了共享锁-排他锁,还有意向共享锁(IS)和意向排他锁(IX);意 向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语 句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁。
4、参考: https:/dev. mysql. com/doc/refman/5. 6/en/innodb-locking. html#innodb-shared-exclusive-lockshttps:/www. cnblogs. com/keme/p/11065025. htmlhttps:/www. jianshu. com/p/7d050498d9dahttps:/blog. csdn. net/laladebon/article/details/82347596-全文完-的更新操作(数据的增删改)、数据DDL的定义语句(包括建表、修改表结构 等)和事务更新类的提交语句。1.1 全局锁
5、的应用场景全局锁的一个非常典型场景为:1、使用mysqldump做全库逻辑备份;2、主库在做完全库逻辑备后在从库上做主从配置。使用mysqldump做初始化 工作。以前的常规做法是使用Flush tables with read lock (FTWRL )锁全库,然 后对整个库进行逻辑备份,命令如下:这种场景下会带来一定的局限性:1 .如在主库mysqldump操作,备份期间数据库不能执行增删改,影响业务正常 使用,在备份时间长的情况下,此操作业务不可容忍;.如在从库mysqldump操作,那么备份期间从库不能执行主库同步过来的 binlog进行同步更新,导致主从延迟。可以在从库上执行如下命令
6、,参考 Seconds_Bchind_Master,多刷几遍命令可以看到参数一直在增大。I;注意:上述场景为不加一singleTransacl ion参数的逻辑备。如果想不影响业 务正常使用,则可使用如下命令:一single-transaction的参数意义,可以使用命令进行查看那么,加全局锁如此不好,备份为什么要加锁呢?这是因为数据一致性的问题,如不加全局锁的话,备份发起时库的数据一致性 和恢复后的数据库一致性不在一个逻辑时间点,会导致备份数据库和恢复数据 库的数据逻辑不一致的。为什么需要全局读锁(FTWRL)官方自带的逻辑备份工具是mysqldumpo当mysqldump使用参数一sing
7、letransaction 的时候, 导数据之前就会启动一个事务,来确保拿到一致性快照 视图。由于MVCC的支持,备份库期间数据是可以正常更新的。MVCC是个嘛?MVCC (Muiti-Version Concurrency Control | 多版本并发控制)TnnoDB 通 过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行 数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是 InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的 系统版本号(LSN) o这是一个随着事务的创建而不断增长的数字。每个事务在 事务开始时会记录它自己的系统
8、版本号。每个查询必须去检查每行数据的版本 号与事务的版本号是否相同。MVCC对普通的SELECT不加锁,直接利用MVCC读取指版本的值,避免了对数据 重复加锁的过程。Undo log是Innodb MVCC重要组成部分,InnoDB的MVCC就 是基于Undo log实现的。InnoDB支持MVCC多版本,其中RC和RR隔离级别是 利用consistent read view方式支持的,即在某个时刻对事物系统打快照记下 所有活跃读写事务ID,之后读操作根据事务ID与快照中的事务ID进行比较, 判断可见性。综上,MVCC的实现,通过保存数据在某个时间点的快照来实现的。意味着一个 事务无论运行多长
9、时间,在同一个事务里能够看到数据一致的视图。根据事务 开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据 可能是不同的。为什么还需要FTWRL ?single-transaction方法只适用于使用Innodb引擎的库。如果有的表使用了 不支持事务的引擎,那么备份就只能通过FTWRL方法。比如,对于My ISAM这 种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那 么就破坏了备份的一致性。所以,就需要使用卜TWRL命令保持非Innodb的一 致性读。这也是DBA要求业务开发人员使用InnoDB替代My ISAM的原因之一。二、表级锁MySQL表级锁有两种:
10、一是表锁,一是元数据锁2. 1表锁表锁的语法是lock tables read/write,示例如下:表锁与FTWRL类似,可用unlock tables主动释放锁,客户端断开时也会自 动释放。注意:lock tables语法除了会限制别的线程的读写外,也限定了本线程接下 来的操作对象。在还没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式。而对于 InnoDB这种支持行锁的引擎,一般不使用lock tables命令来控制并发,毕 竟锁住整个表的影响面还是太大了。2. 2 MDL 锁 另一类表级锁是 MDL (metadata lock) o MySQL 5.5 版本中引入了 MDL,
11、MDL 不需要显式使用,当对一个表做增删改查操作和对表做结构变更操作时候,数 据库会自动加上MDL。读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。读写锁之 间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两 个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。虽然MDL锁是系统默认会加的,但却不能忽略的一个机制。比如在给一个小表 添加个字段,缺导致整个数据库长时间业务不可用。为什么?以下为一个简单 场景解释:在读取elhan_lable时,Sessionl对表做了一个MDL读锁,到了 session2也 对ethan_table加了一个MDL读锁;这
12、时sessionl和session2均可以正常操 作;之后session3需要MDL写锁,会被blocked,是因为session A的 MDL读锁还没有释放,因此只能被阻塞。如果只有session 3自己被阻塞还 好,但是之后所有要在表ethan_table上新申请MDL读锁的请求也会被 session C3阻塞。而所有对表的增删改查操作均需先申请MDL读锁,因此后续 的此类操作都被锁住,业务上来看就感觉此时这个库完全不可读写/不可用了。事务中的MDL锁,在语句执行开始时申请,但是语句结束后并不会马上释放, 而会等到整个事务提交后再释放。若ethan_table表上的查询频繁,且客户端 有重
13、试机制,超时后会再起一个新session请求,一段时间后数据库库的线程 很快爆满,新发起的连接不能成功,业务表象是数据库完全不可用。划重点:行锁都有锁超时设定。但MDL锁没有超时限制,只要事务没提交就会 一直锁。所以,在对大表操作时,大家都会特别小心,但更新小表时,如发生此类现 象,也要学会分析。那怎么分析?怎么解决MDL锁?出现MDL时,就需要提交或者回滚事务。首先要找到这个事务,怎么找?通过in formal ion_schema. innodb_trx查看事务的执行时间trx_started表示什么时候执行的这个事务。使用show full processlist;查看这个线程id,通过
14、其中host字段,到底 是谁连接了数据库,进去commit/rollback。如不是localhost环境,而是应 用程序连接,可联系业务进行commit/rollback/ki 11 o如何正确的给小表加字段?如有库中有长事务,且不提交,则会一直占着MDL锁。使用MySQL的information_schema库的innodb_trx表可查到当前执行中的事务。如做DDL 操作的表有长事务在执行,首先考虑暂停DDL,或kill掉这个长事务。这也 是为什么需要在低峰期做ddl变更的原因。三、InnoDB行锁InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle 不同,
15、后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实 现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则, InnoDB将使用表锁。InnoDB的锁定机制和Oracle数据库有不少相似之处。InnoDB的行级锁定同样 分为两种类型,共享锁和排他锁,而在锁定机制的实现过程中为了让行级锁定 和表级锁定共存,InnoDB也同样使用了意向锁(表级锁定)的概念,也就有了 意向共享锁和意向排他锁这两种。这里本文只介绍概念,后续将进行相应实验 验证。什么是共享锁和排他锁?当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁 定着自己需要的资源的时候,自己可
16、以再加一个共享锁,不过不能加排他锁。但是,如果遇到自己需要锁定的资源已经被一个排他锁占有之后,则只能等待 该锁定释放资源之后自己才能获取锁定资源并添加自己的锁定。而意向锁的作 用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经 被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向 锁。如果自己需要一个共享锁,那么就在表上面添加一个意向共享锁。而如果 自己需要的是某行(或者某些行)上面添加一个排他锁的话,则先在表上面添 加一个意向排他锁。意向共享锁可以同时并存多个,但是意向排他锁同时只能 有一个存在。所以,可以说InnoDB的锁定模式实际上可以分为四种:共享锁(S),排他锁(X),意向共享锁(IS)和意向排他锁(IX),我们可以通过 以下表格来总结上面这四种所的共存逻辑关系:以下是一些注意事项:1 .在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。2 . MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不 同行的记录,但如果是使用相同的索引键,会出现锁冲突。