当前位置: 代码网 > it编程>数据库>Mysql > 浅谈MySQL对于SELECT语句是否会自动加锁

浅谈MySQL对于SELECT语句是否会自动加锁

2026年07月30日 Mysql 我要评论
mysql 对于 select 语句是否加锁取决于​​事务隔离级别​​和​​查询方式​​,以下是全面分析:一、不同隔离级别下的 select 加锁行为隔离级别普通 select 是否加锁说明read

mysql 对于 select 语句是否加锁取决于​​事务隔离级别​​和​​查询方式​​,以下是全面分析:

一、不同隔离级别下的 select 加锁行为

隔离级别普通 select 是否加锁说明
read uncommitted❌ 不加锁可能读取未提交数据(脏读)
read committed❌ 不加锁基于 mvcc 读取最新提交版本
repeatable read❌ 不加锁基于 mvcc 读取事务开始时快照
serializable✅ 加共享锁 (s锁)所有 select 自动转为 lock in share mode

二、显式加锁的 select 语句

即使在不自动加锁的隔离级别,可以通过以下方式强制加锁:

1. 加排他锁 (for update)

select * from orders 
where user_id = 5 
for update; -- 加 x 锁,阻塞其他写操作

2. 加共享锁 (lock in share mode)

select * from products 
where stock > 0 
lock in share mode; -- 加 s 锁,允许并发读但阻塞写

三、特殊场景下的隐式加锁

1. 外键约束检查

delete from parent_table where id = 10;
-- 子表的 select 检查会加共享锁

2. 唯一键冲突检查

insert into users (email) values ('test@example.com');
-- 插入前的唯一性检查会加共享锁

3. insert ... select

insert into archive_users
select * from users 
where created_at < '2020-01-01'; 
-- 对源表 users 的扫描可能加锁

四、innodb 的 mvcc 机制

mysql 通过多版本并发控制实现非锁定读:

graph td
    a[事务开始] --> b[创建read view]
    b --> c{查询}
    c -->|读取| d[最新提交版本]
    c -->|修改| e[创建新版本]
    e --> f[写入undo log]

五、查看 select 锁状态

1. 查看当前锁

select * from performance_schema.data_locks 
where thread_id = ps_current_thread_id();

2. 监控锁等待

select * from sys.innodb_lock_waits;

六、各隔离级别下的锁表现对比

操作rurcrrserializable
普通 select无锁无锁无锁共享锁
update行级x锁行级x锁行级x锁+间隙锁行级x锁
insert隐式x锁隐式x锁隐式x锁+间隙锁隐式x锁
delete行级x锁行级x锁行级x锁+间隙锁行级x锁

七、最佳实践建议

​优先使用默认的 rr 隔离级别​

set session transaction isolation level repeatable read;

​只对需要加锁的查询使用 for update​

-- 仅当需要后续更新时加锁
start transaction;
select balance from accounts where id=1 for update;
update accounts set balance = balance - 100 where id=1;
commit;

​避免长时间持有锁​

-- 设置锁等待超时
set innodb_lock_wait_timeout = 30;

​监控长事务​

select * from information_schema.innodb_trx 
order by time_ms desc limit 10;

​使用覆盖索引减少锁冲突​

-- 创建覆盖索引
alter table orders add index idx_user_status (user_id, status);
-- 使用覆盖索引查询
select order_id from orders 
where user_id = 5 and status = 'pending';

总结

在 mysql 的默认隔离级别(repeatable read)下:

  • ​普通 select 语句不会加任何锁​​,通过 mvcc 机制实现非阻塞读
  • 只有显式使用 for updatelock in share mode 时会加锁
  • serializable 隔离级别会自动为 select 加共享锁

理解这些机制对于设计高并发应用至关重要,既能保证数据一致性,又能最大化系统吞吐量。

到此这篇关于浅谈mysql对于select语句是否会自动加锁的文章就介绍到这了,更多相关mysql select自动加锁内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com