在MySQL中,锁是实现并发控制的一种机制,用于管理对数据库中数据的访问。MySQL支持多种类型的锁,包括表锁和行锁。行锁是较为先进的锁机制,因为它允许多个事务同时对数据库中的不同行进行操作,从而提高并发性能。然而,如果不正确管理,即使是行锁也可能导致死锁。

行锁
行锁是MySQL中较为常见的一种锁机制,它允许多个事务对不同的行进行操作,而不会互相干扰。InnoDB存储引擎使用行锁来实现其多版本并发控制(MVCC)。
死锁
死锁是指两个或多个事务在执行过程中,因互相等待对方释放资源而无法继续执行的情况。例如,事务A持有资源B并请求资源C,同时事务B持有资源C并请求资源A。
避免死锁的策略
innodb_lock_wait_timeout参数,该参数定义了事务等待锁的最长时间。超过这个时间后,事务会自动回滚以避免死锁。SHOW ENGINE INNODB STATUS命令查看死锁日志,分析死锁原因。INNODB_TRX, INNODB_LOCKS, INNODB_LOCK_WAITS表查询当前的事务和锁情况。在MYSQL里把锁分为三类:
全局锁、表锁、行级锁
全局锁:
在使用了flush tables with read lock语句之后,全库都会进入
只读状态
,数据库执行增删改和修改表结构的操作时,都会被阻塞;主要用于在全表进行备份时,防止其他事务修改表的数据
表级锁:
表锁:
使用lock tables语句就会给表上锁,限制其他线程访问这张表,这里对线程有两种限制方式:
1.读锁 lock tables 表名 read
本线程:可读,不能写
其他线程:可读,不能写
2.写锁 lock tables 表名 write
本线程:可读可写
其他线程:读写全都阻塞
元数据锁:
对表上一个MDL锁,如果是对表进行
CRUD操作
,会对表上
MDL读锁
,如果是
修改表的结构
,就会对表上一个
MDL写锁
,MDL锁的作用是防止线程在操作表时,其他线程影响表的结构和数据
意向锁
:
当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。意向锁用于确定这个表是否有行级锁
两类意向锁:
行级锁:
InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。记录锁(Record Lock):分为S读锁和X写锁,满足读写互斥和写写互斥
| 已有锁 | 加 S 锁 | 加 X 锁 |
|---|---|---|
| S 锁 | 允许 | 阻塞 |
| X 锁 | 阻塞 | 阻塞 |
间隙锁(Gap Lock):只存在于可重复读隔离级别,是为了解决可重复读(RR)隔离级别下的幻读现象。
临键锁(Next-key Lock):记录锁 + 间隙锁合体,会锁定一个范围,并锁定这个范围的数据
InnoDB有哪些锁呢:行级锁、表锁、意向锁
这里不是有一个升级阈值一样的规定,所谓 “行锁变表锁”,是看起来像锁表,本质是锁了全表所有行 / 大范围间隙,效果等价于表锁。
InnoDB 行锁依托索引生效,
无索引 / 索引失效
时会全表扫描
,行操作就会查询全表,然后给所有行加锁效果等价于表锁
因为临建锁 = 间隙锁 + 记录锁,利用这两个锁的机制就可以大幅度的减少幻读的发生
两个事务互相持有对方的锁,并且
自身不会主动释放锁
,互相陷入等待的循环就是锁查看最近死锁日志
show engine innodb status;
日志里看:阻塞 SQL、持有锁、等待锁、事务执行顺序,定位冲突语句
主要是了解了mysql里面所有的锁的定义,行锁与表锁并不是字面意思上的转换,而是效果上在全盘扫描时实现了锁全表的现象,临键锁解决幻读,从临键锁的组成来分为锁数据(记录锁)和锁数据前后的空白间隙(间隙锁),以及死锁的相关知识。