Snowflake执行SELECT时是否锁表?SELECT与TRUNCATE并发场景咨询
SELECT与TRUNCATE的锁机制冲突分析
场景回顾
用户A对一张大表执行
SELECT查询,该查询预计运行30秒。用户B在10秒后对该表执行TRUNCATE操作。
这个问题的核心是不同数据库的锁机制和DDL处理逻辑差异,以下分主流数据库逐一说明:
MySQL(InnoDB引擎)
- 普通
SELECT(默认快照读,RR隔离级别):
普通查询不会加表级锁,而是基于事务启动时的一致性快照读取数据。TRUNCATE属于DDL操作,会请求排他表锁,由于SELECT不持有锁,TRUNCATE会立即执行。此时正在运行的SELECT会因为表结构被修改(TRUNCATE等价于删表重建)抛出Error 1412: Table definition has changed, please retry transaction错误,查询中断,但中断前已经读取的快照数据是有效的。 - 加锁读(如
SELECT ... FOR UPDATE/SELECT ... LOCK IN SHARE MODE):
这类查询会持有表级共享锁,TRUNCATE的排他锁需要等待共享锁释放才能获取,因此会等用户A的SELECT执行完成后再执行。这种情况下A能正常获取全部数据,之后B的TRUNCATE才会清空表。
PostgreSQL
PostgreSQL中SELECT默认采用快照读,不会持有任何表级锁。而TRUNCATE需要获取ACCESS EXCLUSIVE锁(最严格的表级锁,会阻塞所有其他表操作),这个锁的获取必须等待当前所有访问该表的事务结束。因此用户A的SELECT会正常跑完30秒并拿到数据,之后用户B的TRUNCATE才会执行并清空表。
SQL Server
TRUNCATE TABLE会获取SCH-M(架构修改)锁,该锁会阻塞所有对表的读写操作。无论SELECT是否启用行版本控制(快照读),SCH-M锁都需要等待当前正在运行的SELECT查询完成才能获取。因此用户A的查询会正常完成并获取数据,之后用户B的TRUNCATE才会执行。
内容的提问来源于stack exchange,提问作者alexspurlock
相关产品推荐
相关产品推荐

