MySQL 的锁按照范围能够分为全局锁、表锁、行锁,其中行锁是由数据库引擎实现的,并非全部的引擎都提供行锁,MyISAM 就不支持行锁,因此文章介绍行锁会以InnoDB引擎为例来介绍行锁。html
MySQL 提供全局锁来对整个数据库实例加锁。mysql
语法:sql
FLUSH TABLES WITH READ LOCK
这条语句通常都是用来备份的,当执行这条语句后,数据库全部打开的表都会被关闭,而且使用全局读锁锁定数据库的全部表,同时,其余线程的更新语句(增删改),数据定义语句(建表,修改表结构)和更新类的事务提交都会被阻塞。数据库
在mysql 8.0 之后,对于备份,mysql能够直接使用备份锁。安全
语句:session
LOCK INSTANCE FOR BACKUP UNLOCK INSTANCE
这个锁的做用范围更广,这个锁会阻止文件的建立,重命名,删除,包括 REPAIR TABLE TRUNCATE TABLE, OPTIMIZE TABLE
操做以及帐户的管理都会被阻塞。固然这些操做对于内存临时表来讲是能够执行的,为何内存表不受这些限制呢?由于内存表不须要备份,因此也就不必知足这些条件。多线程
Mysql的表级别锁分为两类,一类是元数据锁(Metadata Lock,MDL),一种是表锁。线程
元数据锁(MDL) 不须要显式使用,在访问一个表的时候会被自动加上。这个特性须要MySQL5.5版本以上才会支持,当对一个表作增删改查的时候,该表会被加MDL读锁;当对表作结构变动的时候,加MDL写锁。MDL锁有一些规则:code
因此咱们在操做数据库表结构时候必需要注意不要使用长事务,这里具体是什么意思呢?我举个例子说明下:htm
,它主要的目的就是表示将要锁定表中的行或者正在锁定表中的行。
意向锁根据和行锁的组合能够分为:
意向排他锁:代表将要在表中的某些行获取排他锁
意向共享锁:代表将要在表中的某些行获取共享锁
意向锁的获取必须在行锁获取以前,也就是说获取共享锁以前必须先要获取共享意向锁,对于排他锁也是同样的道理。
那么这个意向锁到底有什么做用呢?
解释这个以前,咱们先看看意向锁和行锁以前的兼容关系:
--- | 排他锁(X) | 意向排他锁(IX) | 共享锁(S) | 意向共享锁(IS) |
---|---|---|---|---|
排他锁(X) | 冲突 | 冲突 | 冲突 | 冲突 |
意向排他锁(IX) | 冲突 | 兼容 | 冲突 | 兼容 |
共享锁(S) | 冲突 | 冲突 | 兼容 | 兼容 |
意向共享锁(IS) | 冲突 | 兼容 | 兼容 | 兼容 |
咱们假设有2个事务A和事务B,事务获取到了共享锁,锁住了表中的某一行,这一行只能读,不能写,如今事务B要申请整个表的写锁。若是事务B申请成功,那么确定是能够对表中全部的行进行写操做的,那么确定与A获取的行锁冲突。数据库为了不这种冲突,就会进行冲突检测,那么如何去检测呢?有两种方式:
判断表中的每一行须要遍历全部记录,效率太差,因此数据库就用第一种方式去作冲突检测,也就是用到了意向锁。
本文主要从MySQL的加锁范围来分析了MySQL的锁,MySQL根据加锁范围能够分为全局锁、表锁、行锁。全局锁和表锁是MySQL本身实现,行锁都是由引擎层面去实现。InnoDB下的行锁主要分为共享锁和排他锁。共享锁请求后,行只能读,共享锁之间不互斥。排他锁获取后能更新和删除行,排他锁与其余锁都互斥。最后我在行锁的基础上提到了意向锁,意向锁主要表示正在锁住行或者即将锁住行,为了在锁冲突检测中提升效率。固然InnoDB下还有其余锁,好比间隙锁,记录锁,Next-Key锁等,这些都不在本文的探讨范围以内,若有兴趣的同窗能够自行研究。
《MySQL实战45讲》