锁的基本概念与分类
1. 什么是锁?
锁是数据库实现并发控制的核心手段,能够确保多人同时操作数据库时,数据的一致性和完整性不受破坏,保障系统正常运行。
2. MySQL 支持的锁类型
MySQL 提供三类核心锁,不同存储引擎对锁的支持存在差异:
| 锁类型 | 说明 | 支持存储引擎 |
|---|---|---|
| 全局锁 | 对整个数据库实例加锁,使数据库进入只读状态 | 所有存储引擎 |
| 表级锁 | 对整张数据表加锁,锁定粒度较大 | InnoDB、MyISAM |
| 行级锁 | 对单个行记录加锁,锁定粒度最小 | InnoDB |
死锁相关问题
1. 什么是死锁?
死锁是指两个或多个进程在执行过程中,因相互争夺资源而陷入互相等待的状态,若无外力干预,所有进程都无法继续推进,导致事务阻塞。
2. 死锁的处理方式
-
超时等待:通过
innodb_lock_wait_timeout参数设置超时时间(默认 50s),事务等待超时后自动释放资源。 -
死锁检测(默认开启):设置
innodb_deadlock_detect = on,数据库会主动检测死锁,发现后回滚其中一个事务,确保其他事务正常执行。
3. 死锁的查看方式
-
执行命令
show engine innodb status,可查看最近一次死锁的详细信息。 -
开启 InnoDB Lock Monitor 锁监控,系统每 15s 输出一次锁相关日志;使用完毕后建议关闭,避免占用过多资源影响数据库性能。
4. 死锁检测的开启
innodb_deadlock_detect 参数默认值为 on,即默认开启死锁检测;若已关闭,可通过修改该参数重新开启。
5. InnoDB 对死锁的默认处理
InnoDB 默认采用超时策略处理死锁,innodb_lock_wait_timeout 参数默认时长为 50s,超时后阻塞的事务会被终止。
全局锁
1. 什么是全局锁?
全局锁是对整个数据库实例施加的锁,加锁后数据库进入只读状态,数据更新语句、数据定义语句、更新类事务的提交语句等操作都会被阻塞。
2. 应用场景
典型场景为全库逻辑备份,通过加全局锁确保备份过程中数据的一致性。
3. 设置方式
执行命令 flush tables with read lock(简称 FTWRL),即可为数据库添加全局只读锁。
4. 潜在问题
-
主库备份:备份期间无法执行更新操作,导致业务停摆。
-
从库备份:备份期间无法同步主库的 binlog 日志,引发主从延迟。
5. 其他设置只读的方式
除 FTWRL 外,还可通过命令 set global readonly=true 将数据库设置为只读状态。
6. FTWRL 与 set global readonly=true 的区别
两者核心区别在于客户端断开后的行为:
-
FTWRL:客户端断开连接后,数据库会自动取消只读状态。
-
set global readonly=true:客户端断开后,数据库仍保持只读状态,需手动修改参数恢复。
共享锁与排他锁
1. 共享锁(读锁,read lock)
-
定义:由读取操作创建的锁,支持并发读。
-
特性:多个事务可同时对同一数据添加共享锁;加锁期间,任何事务无法修改数据(即无法获取排他锁),需等待所有共享锁释放。
2. 排他锁(写锁,writer lock)
-
定义:由写操作相关的事务创建的锁,是悲观锁的一种实现。
-
特性:某事务对数据加排他锁后,仅该事务可对数据执行写操作;其他事务可读取数据,但无法执行写操作,也不能添加任何锁,需等待排他锁释放。
3. 锁的手动添加方式
-
共享锁:执行
SELECT … LOCK IN SHARE MODE,MySQL 会对查询结果集中的每行添加共享锁(前提:当前线程未对结果集中的行使用排他锁,否则申请会阻塞)。 -
排他锁:执行
SELECT ... FOR UPDATE,MySQL 会对查询结果集中的每行添加排他锁;事务中对记录的更新、删除操作会自动添加排他锁(前提:当前无其他线程对结果集中的行使用排他锁或共享锁,否则申请会阻塞)。
InnoDB 存储引擎的锁算法与行锁实现
1. 锁算法类型
InnoDB 提供三种锁算法,用于实现不同粒度的锁定:
-
Record Lock:单个行记录上的锁,锁定粒度最小。
-
Gap Lock:间隙锁,锁定一个数据范围,不包含范围边界的记录本身。
-
Next-Key Lock:锁定一个数据范围,包含范围边界的记录本身(默认锁算法)。
2. 行锁的实现
行级锁是 MySQL 中粒度最小的锁,能最大程度减少并发操作的冲突,其实现依赖上述锁算法,具体通过共享锁和排他锁的添加逻辑实现(详见“共享锁与排他锁”章节)。
逻辑备份的优化方案
使用全局锁备份会导致数据库无法插入数据,官方提供的 mysqldump 工具可解决该问题:
在执行备份时添加参数 -single-transaction,工具会在导入数据前启动一个事务,通过事务的隔离性保证数据一致性,同时支持备份期间的数据更新操作。


