| 为了尽可能提高数据库的并发度,每次锁定的数据范围越小越好,理论上每次只锁定当前操作的数据的方案会得到最大的并发度, |
| 但是管理锁是很耗资源的事情(涉及获取、检查、释放锁等动作)。因此数据库系统需要在高 并发响应和系统性能两方面进行平衡, |
| 这样就产生了“锁粒度(Lock granularity)”的概念。 |
| |
| 对一条记录加锁影响的也只是这条记录而已,我们就说这个锁的粒度比较细;其实一个事务也可以在表级别进行加锁,自然就被称之为表级锁或者表锁, |
| 对一个表加锁影响整个表中的记录,我们就说这个锁的粒度比较粗。锁的粒度主要分为表级锁、页级锁和行锁 |
| 该锁会锁定整张表,它是MySQL中最基本的锁策略,并不依赖于存储引擎(不管你是MySQL的什么存储引擎,对于表锁的策略都是一样的), |
| 并且表锁是开销最小的策略(因为粒度比较大)。由于表级锁一次会将整个表锁定,所以可以很好的避免死锁问题。当然,锁的粒度大 |
| 所带来最大的负面影响就是出现锁资源争用的概率也会最高,导致并发率大打折扣 |
| 在对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级别的S锁或者X锁的。 |
| 在对某个表执行一些诸如ALTER TABLE、DROP TABLE这类的DDL语句时,其他事务对这个表并发执行诸如SELECT、INSERT、 |
| DELETE、UPDATE的语句会发生阻塞。同理,某个事务中对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,在其他 |
| 会话中对这个表执行DDL语句也会发生阻塞。这个过程其实是通过在server层使用一种称之为元数据锁(英文名:Metadata Locks, |
| 简称MDL)结构来实现的 |
| 一般情况下,不会使用InnoDB存储引擎提供的表级别的S锁和X锁。只会在一些特殊情况下,比方说崩溃恢复过程中用到。 |
| 比如,在系统变量autocommit=0,innodb_table_locks=1时,手动获取InnoDB存储引擎提供的表t的S锁或者X锁可以这么写: |
| |
| LOCK TABLES t READ:InnoDB存储引擎会对表t加表级别的S锁 |
| LOCK TABLES t WRITE:InnoDB存储引擎会对表t加表级别的X锁 |
| |
| show open tables where in_use > 0 |
| |
| |
| lock table mylock read; |
| |
| |
| unlock tables; |
-
结论

-
代码演示
| # 在第1个连接中,开启1个事务 |
| begin; |
| # 开启1个读锁 |
| lock table mylock read; |
| # 测试自己是否可读 |
| select * from mylock; |
| # 测试自己是否可写,执行报错 |
| insert into mylock ... |
| # 测试自己是否可以操作其他表,执行报错 |
| select * from user; |
| # 打开1个新的连接,测试在新的连接中是否可以读这个表 |
| select * from mylock; |
| # 在第2个连接中测试是否可以写这张表,处于等待状态 |
| insert into ... |
| # 在第1个连接中释放这个锁或者结束这个会话之后,其他连接才可以写这张表 |
| InnoDB 支持 多粒度锁(multiple granularity locking) ,它允许 行级锁 与 表级锁 共存,而意向锁就是其中的一种表锁 |
| 意向锁是由存储引擎 自己维护的 ,用户无法手动操作意向锁,在为数据行加共享或者排他锁之前,InooDB 会先获取该数据行 所在数据表的对应意向锁 |
| |
| 使用场景:当用户想为某个表添加1个共享锁或排他锁的时候,这时需要把表中的所有数据检索1遍,检查表中是否有锁,如果表中的数据较多,这时检索的时候就会消耗很多资源; |
| 所以当我们为某个表或某个页添加锁后,数据库会自动为上一级添加1个意向锁;其他用户想要为这个表再次添加锁的时候,就能直接知道这张表已经添加了锁,不需要再检索整个表 |
| # 添加意向共享锁:添加共享锁的时候会自动添加意向共享锁 |
| SELECT column FROM table ... LOCK IN SHARE MODE; |
| # 添加意向排他锁:添加排他锁的时候会自动添加意向排他锁 |
| SELECT column FROM table ... FOR UPDATE; |
| |
| # 案例1 |
| # 为某1行添加X锁,数据库会自动为页上添加意向X锁 |
| select * from user where id = 7 for updata; |
| # 这时在新的连接或新的事务中继续添加锁时,就不会检索该表中的所有数据 |
| |
| # 案例2 |
| # 为表中的某1行添加1个S锁,数据库自动为页添加1个意向S锁 |
| # 为该表的另1行添加1个S锁,没有冲突,数据库自动为页添加1个意向S锁,这2个意向S锁是兼容的 |
| 1. InnoDB 支持 多粒度锁 ,特定场景下,行级锁可以与表级锁共存。 |
| 2. 意向锁之间互不排斥,但除了 IS 与 S 兼容外, 意向锁会与 共享锁或排他锁互斥 。 |
| 3. IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。 |
| 4. 意向锁在保证并发性的前提下,实现了 行锁和表锁共存 且 满足事务隔离性 的要求 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术