MySQL中锁的类型

本文深入探讨了InnoDB存储引擎的两种行级锁——共享锁和排他锁的工作原理及其兼容性,介绍了意向锁的概念与作用,展示了如何利用InnoDB提供的工具监控并分析锁的状态,帮助读者更好地理解InnoDB中的锁机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

InnoDB存储引擎实现了一下两种标准的行级锁:

共享锁S LOCK 允许事务读一行数据

排他锁 X LOCK 允许事务删除或更新一行数据

如果是一个事务T1斤获得了行r的共享锁,那么另外一个事务T2可以立即获得行r的共享锁,因为读取并没有改变行r的数据,称这种情况为锁兼容Lock Compatible。但若有其他事务T3想获得行r的排他锁,则必须等待事务T1、T2释放行r的共享锁---这种情况称为锁不兼容

可以看到 X锁与任何锁都不兼容,而S锁仅和S锁金融。需要特别注意,S和X都是行锁,兼容是指通一行记录row锁的兼容情况

此外,InnoDB支持多粒度granular锁定。这种锁定允许事务在航级别上的锁和表级别上的锁同时存在。为了支持在不通粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度(fine granularity)上进行枷锁。

若将上锁的对象看成一棵树,那么对最上层的对象上锁,也就是对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁,如上图,如果需要对页上的记录r进行上X锁,那么分别需要对数据A、表、页上意向锁IX,最后对记录r上X锁,若其中任何一部分导致等待,那么该操作需要等待粗粒度锁的完成,举例来说,在对记录r及杀死那个X锁之前,已经有事务对表1进行了S表锁,那么表1已存在S锁,之后事务需要对记录r在表上系上IX,由于不兼容,那么该事物需要等待表锁操作的完成

InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别锁。设计目的主要是为了在一个事务上揭示下一个行将别请求的锁类型。其支持两种意向锁

意向共享锁 IS LOCK 事务想要获得一张表中某几行的共享锁

意向排他锁 IX LOCK 事务想要获得一张表中某几行的排他锁

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实是不会阻塞出全表扫以外的任何请求

 

可以通过SHOW ENGINE INNODB STATUS来查看当前锁请求的信息

可以看到SQL语句 select * from t where a<4 lock in share mode在等待。RECODE LOCKS space id 30 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t' trx id 48B89BD lock_mode X locks rec but not gap 表示锁住的资源。locks rec but not gap代表锁住的是一个索引,而不是一个范围

在InnoDB 1.0 版本之前,用户只能通过SHOW FULL PROCESSLIST,SHOW ENGINE INNODB STATUS来查看当前数据库中锁的请求,然后在判断事物锁的情况,从InnoDB 1.0开始。在Information_schema架构下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。通过这三张表,用户可以更方便的监控到当前事务并发分析可能存在的锁问题。看一下INNODB_TRX结构

通过state可以观察到trx_id为730FEE的事务当前正在运行,而trx_id为731F4的事务处于LOCK WAIT状态,且运行的SQL语句是select * from parent lock in shar mode。该表只是显示了当前运行的innoDB事务,并不能准确的判断锁的一些情况。如果需要查看锁,还需要访问 INNODB_LOCKS

用户可以清楚的看到当前锁的信息,trx_id为730FEE的事务想表parent加了一个X的行锁。ID为7311F4的事务想表parent申请了一个S的行锁。lock_data都是1,申请相同的资源,因此会有等待。这样可以解析INNODB_TRX为什么一个事务的trx_state是RUNNING另一个是LOCK WAITLE

另外需要注意的是,发现lock_data并不是可信的值。例如当用户运行一个范围查找时,lock_data可能只返回第一行的主键值。与此同时,如果当前资源被锁住了。若锁住的页因为InnoDB存储引擎缓冲池的容量,导致页从缓冲池中被刷出,则查看INNODB_LOCKS表时,该值同样显示为NULL。即InnoDB存储引擎不会从磁盘进行再一次的查找

在通过INNODB_LOCKS馋看了每张表上锁的情况后,用户可以判断由此引发的等待情况。当事务较小时,用户就可以人为地、直观地进行判断了。但是当事务量非常大,其中锁和等待也时常发生。这个时候就不容易判断。但是可以通过INNODB_LOCK_WAITS可以很直观的反应出当前事务的等待。表INNODB_LOCK_WAITS由4个字段组成

通过上述的SQL语句,用户可以清楚的看到哪个事务阻塞了另一个事务。当然这只是给出了事务和锁ID,如果需要,用户可以根据表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS得到更为直观的详细信息。例如,用户可以执行如下联合查询

 

转载于:https://www.cnblogs.com/olinux/p/5174235.html

### MySQL 类型概述 在MySQL中,机制用于确保数据的一致性和完整性,防止多个事务同时修改相同的数据而导致冲突。根据不同的应用场景和需求,MySQL提供了多种类型来实现这一目标。 #### 表级 (Table-Level Locks) 表级是最简单的定策略之一,适用于较低并发量的应用环境。当一个会话获得了一张表上的写入时,其他任何试图对该表进行读取或写入操作的会话都将被阻塞直到前者的操作完成并释放[^1]。这种类型虽然简单易懂,但在高并发环境下效率低下,因为它不允许多线程并发执行针对同一表格的操作。 #### 全局 (Global Locks) 全局可以看作是一种极端形式的表级——它不仅限于单个特定的表而是作用在整个实例上。这意味着一旦设置了全局只读模式或其他类似的全库范围内的定措施,则整个服务器内所有未提交的事物都不能再做更改动作;新发起的一切DML语句都会失败除非它们属于那些已经被允许例外处理的情况之外。显然这通常仅用于维护期间如备份恢复等特殊时刻而非日常业务流程之中。 #### 记录 (Row-Level Locks 或 Record Locks) 相比之下更为精细的是记录级别的定方式,也就是常说的行为级或者行级别定。这类方法能够精确到具体某一行甚至某个字段上面去实施保护从而极大提高了系统的吞吐能力特别是在面对大量并发请求的时候表现尤为突出。例如,在`SELECT ... FOR UPDATE`查询里指定条件匹配到的结果集会被加上排他性的X以阻止其它连接对其进行更新删除之类的变更行为直至当前事物结束为止[^3]。 ```sql -- 加读取一条记录 SELECT * FROM table_name WHERE id = 1 FOR UPDATE; ``` 通过上述三种主要类别可以看出,不同层次的定各有优劣之处,合理选用取决于具体的使用场景和技术架构考量因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值