表锁、行锁、共享锁和排他锁(读锁写锁)、意向锁、间隙锁

数据库中的锁

  • 如果按照锁的粒度来分的话,分为表锁和行锁;如果按照读写功能来分的话,分为读锁和写锁。

表锁

  • 特点: 即使操作一条记录也会锁住整个表,锁定粒度较大,发生锁冲突的概率高,并发度最低。但开销小,加锁快,而且不会出现死锁。
  • 表锁是mysql中开销最小的策略,它会锁定整张表,用户在对表进行写操作前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。

行锁

  • 特点: 操作时只锁某些行,不对其它行有影响,锁粒度较小,发生锁冲突的概率低,并发度高。但开销大,加锁慢,而且会出现死锁。
  • 行锁可以最大程度的支持并发处理,同时也带来了最大的锁开销,InnoDB存储引擎实现了两种行锁:共享锁和排他锁。

InnoDB 的行锁是怎么实现的?

  • InnoDB 行锁是通过索引上的索引项来实现的。意味着:只有通过索引条件检索数据,InnoDB 才会使用行级锁,否则,InnoDB将使用表锁!

  • 对于主键索引:直接锁住主键索引即可。

  • 对于普通索引:先锁住普通索引,接着锁住主键索引,这是因为一张表的索引可能存在多个,通过主键索引才能确保锁是唯一的,不然如果同时有2个事务对同1条数据的不同索引分别加锁,那就可能存在2个事务同时操作一条数据了。

共享锁和排他锁

  • mysql的锁机制分为表级锁和行级锁,共享锁和排他锁都属于行级锁。
  • 共享锁又称为读锁,简称S锁,指多个事务对同一数据可以共享一把锁,他们都能访问到这个数据,但只能读不能改。
  • 排他锁又称为写锁,简称X锁,它不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,那其他事务就不能再获取该行的其他锁了,包括共享锁和排他锁。而获取了这个排他锁的事务可以对数据行进行读和写。
  • 常见的几种 SQL 语句的加锁情况如下:
    select * from table:不加锁
    update/insert/delete:排他锁
    select * from table where id = 1 for update:id为索引,加排他锁
    select * from table where id = 1 lock in share mode:id为索引,加共享锁

意向锁

  • 意向锁是一种表级锁,如果事务想要给表中几行数据加上行级共享锁,那么需要先在表级别加上意向共享锁(IS);如果事务想要给表中几行数据加上行级排他锁,那么需要先在表级别加上意向排他锁(IX)。
  • 目的/作用:当向一个表添加表级排他锁或表级共享锁时,如果没有意向锁的存在,则需要遍历整个表来判断是否存在不兼容的行锁,以免发生冲突。如果有了意向锁,只需要判断该意向锁与想添加的表级锁是否兼容即可,因为意向锁的存在代表了有行级锁的存在,所以无需遍历整个表就可以获取结果,减少了整个检查过程,将检查每一行的排他锁变成只检查一个意向锁。

间隙锁

  • 间隙锁指的是锁定一个范围内的索引记录,开区间,不包括双端端点,对于键值在条件范围内但不存在的记录,叫做间隙,间隙锁也会对这个间隙加锁。
  • 目的/作用:让其他事务无法在间隙中新增数据,从而防止了幻读。
  • 在可重复读的隔离级别下才能生效。
<think>嗯,用户问的是MySQL中的语法使用示例。我需要先回忆一下MySQL的机制,确保自己理解正确。是两种不同的粒度,定整个,而则只定特定的。首先,的语法应该是用LOCK TABLES命令吧?比如LOCKTABLEStable_nameREAD/WRITE,然后UNLOCK TABLES来释放。记得会影响并发性能,因为一旦住,其他会话就不能访问了,除非是的情况下允许其他。然后是在InnoDB中默认是通过索引来实现的。比如SELECT... FORUPDATE或者SELECT ...LOCKIN SHARE MODE。不过用户可能想知道具体的语法示例,比如在事务中如何显式地加。需要提醒用户是在事务提交后才会释放,所以要注意事务的持续时间,避免长时间导致阻塞。 还要注意用户提到的引用内容,比如引用1中的例子,涉及到next-key lock意向锁。可能用户对的机制有一定了解,需要结合示例说明。比如在SELECT查询中使用FOR UPDATE来加,或者在更新语句中自动加。 另外,引用3提到了插入意向锁,这有关系吗?可能用户混淆了不同的类型,需要明确插入意向锁属于间隙锁的一种,不同,但可能同时存在。这部分可能需要简要说明,但用户主要问的是语法,所以可能不需要深入。用户可能还需要知道如何查看当前的信息,比如引用1中的performance_schema.data_locks。可以给出查询信息的SQL示例,帮助用户调试。还要注意区分MyISAMInnoDB存储引擎,因为MyISAM默认使用,而InnoDB支持。所以在示例中需要明确存储引擎的类型,避免用户混淆。 需要检查语法是否正确,比如FORUPDATE的位置是否正确,是否需要在事务中使用。例如,在事务开始时执BEGIN,然后执的SELECT,最后COMMIT释放。可能用户还关心的兼容性冲突情况,比如之间的冲突,但用户的问题主要是语法使用示例,这部分可以简要提及。总结一下,回答的结构应该是先介绍的语法示例,再介绍的语法示例,最后给出查看信息的方法。同时要注意引用中的相关内容,比如意向锁间隙锁,但重点放在用户需求的语法示例上。</think>### MySQL语法及示例 --- #### 一、语法及示例 **1. 显式语法** 通过`LOCK TABLES`命令实现,分为**共享**(`READ`)**独占**(`WRITE`): ```sql -- 加 LOCK TABLES table_name READ; -- 共享(允许其他会话,禁止) LOCK TABLES table_name WRITE; -- 独占(禁止其他会话) -- 解 UNLOCK TABLES; ``` **2. 示例场景** - **共享**:允许并发查询,禁止入: ```sql LOCK TABLES orders READ; SELECT * FROM orders WHERE user_id = 100; UNLOCK TABLES; ``` - **独占**:批量更新时禁止其他操作: ```sql LOCK TABLES orders WRITE; UPDATE orders SET status = 'closed' WHERE create_time < '2023-01-01'; UNLOCK TABLES; ``` --- #### 二、语法及示例 **1. 隐式(自动加)** InnoDB引擎在`UPDATE`/`DELETE`语句中自动对符合条件的加**排他**(X): ```sql BEGIN; UPDATE users SET balance = balance - 100 WHERE id = 5; -- 自动对id=5的加X COMMIT; ``` **2. 显式语法** 通过`SELECT ... FOR UPDATE`或`SELECT ... LOCK IN SHARE MODE`手动加: - **排他(X)**: ```sql BEGIN; SELECT * FROM products WHERE stock < 10 FOR UPDATE; -- 定库存不足的 UPDATE products SET stock = stock + 100 WHERE stock < 10; COMMIT; ``` - **共享锁(S)**: ```sql BEGIN; SELECT * FROM accounts WHERE user_id = 100 LOCK IN SHARE MODE; -- 允许其他会话,禁止修改 COMMIT; ``` --- #### 三、冲突与性能注意事项 1. **冲突** - 互斥:若会话A持有,会话B无法加[^1]。 - 冲突:`FOR UPDATE`与`LOCK IN SHARE MODE`在同一上会阻塞。 2. **查看信息** 通过`performance_schema.data_locks`分析状态: ```sql SELECT ENGINE, OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_DATA FROM performance_schema.data_locks; ``` --- #### 四、应用场景对比 | 类型 | 适用场景 | 性能影响 | |--------|----------|----------| | | 全操作(如备份) | 高并发下性能差 | | | 高并发事务(如支付) | 需合理设计索引避免死[^3] | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值