SELECT ... FOR UPDATE 加锁后,其他线程能读取数据吗

在执行 SELECT * FROM table WHERE ... FOR UPDATE 语句时,MySQL 会对查询结果集中的行加 排他锁(X锁)。这种锁的行为会影响其他事务对这些行的读写操作。以下是具体的影响:


1. 加锁后的效果

  • 当前事务

    • 对查询结果集中的行加排他锁(X锁)。

    • 可以继续读取和修改这些行。

  • 其他事务

    • 不能对这些行加锁或修改(即不能执行 UPDATEDELETE 或 SELECT ... FOR UPDATE)。

    • 可以读取这些行(如果隔离级别允许),但读取的数据可能是旧版本(取决于隔离级别)。


2. 不同隔离级别下的行为

2.1 读未提交(READ UNCOMMITTED)
  • 其他事务可以读取被锁定的行,即使这些行尚未提交(脏读)。

  • 其他事务不能修改被锁定的行。

2.2 读已提交(READ COMMITTED)
  • 其他事务可以读取被锁定的行,但只能读取已提交的数据(不会脏读)。

  • 其他事务不能修改被锁定的行。

2.3 可重复读(REPEATABLE READ)
  • 其他事务可以读取被锁定的行,但只能读取事务开始时的数据快照(不会脏读或不可重复读)。

  • 其他事务不能修改被锁定的行。

2.4 串行化(SERIALIZABLE)
  • 其他事务不能读取或修改被锁定的行,直到当前事务提交或回滚。


3. 示例

假设有两个事务:事务 A 和事务 B。

事务 A

sql

复制

START TRANSACTION;
SELECT * FROM t WHERE id = 1 FOR UPDATE;  -- 对 id = 1 的行加排他锁
-- 事务 A 可以继续读取或修改 id = 1 的行
事务 B
  • 尝试读取

    SELECT * FROM t WHERE id = 1;  -- 可以读取(取决于隔离级别)
    • 在 读未提交 隔离级别下,事务 B 可以读取事务 A 未提交的数据。

    • 在 读已提交 或更高隔离级别下,事务 B 只能读取已提交的数据。

  • 尝试修改

    UPDATE t SET name = 'Bob' WHERE id = 1;  -- 会被阻塞,直到事务 A 提交或回滚
    • 事务 B 不能修改被锁定的行。

  • 尝试加锁

    SELECT * FROM t WHERE id = 1 FOR UPDATE;  -- 会被阻塞,直到事务 A 提交或回滚
    • 事务 B 不能对锁定的行加锁。


4. 总结

  • 执行 SELECT ... FOR UPDATE 后,其他事务:

    • 可以读取被锁定的行(具体行为取决于隔离级别)。

    • 不能修改或加锁被锁定的行,直到当前事务提交或回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值