[Clickhouse研究]: Clickhouse的同步锁
Clickhouse的存储锁
源码解析
代码主要在IStorage
之中1
2
3
4
5
6
7
8class IStorage
{
TableLockHolder lockForShare;
TableLockHolder lockForAlter;
TableExclusiveLockHolder lockExclusively;
mutable RWLock alter_lock;
mutable RWLock drop_lock;
}
从代码的定义上来, 只有drop和alter相关的才会加锁
排它锁lockExclusively
的锁同时锁住alter_lock
和drop_lock
, 锁类型为写锁1
2
3
4
5
6
7
8
9
10
11
12TableExclusiveLockHolder IStorage::lockExclusively(const String & query_id, const std::chrono::milliseconds & acquire_timeout)
{
TableExclusiveLockHolder result;
result.alter_lock = tryLockTimed(alter_lock, RWLockImpl::Write, query_id, acquire_timeout);
if (is_dropped)
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
result.drop_lock = tryLockTimed(drop_lock, RWLockImpl::Write, query_id, acquire_timeout);
return result;
}
排它锁只有很少的地方用到
- 在renameTable时候用到
- 在DropTable的时候用到
- 在restartReplica时候用到
修改锁lockForAlter
只锁了alter
, 锁类型为写锁1
2
3
4
5
6
7
8
9TableLockHolder IStorage::lockForAlter(const String & query_id, const std::chrono::milliseconds & acquire_timeout)
{
TableLockHolder result = tryLockTimed(alter_lock, RWLockImpl::Write, query_id, acquire_timeout);
if (is_dropped)
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
return result;
}
都只在修改DDL时候用到: DDL语句执行和复制表的同步DDL时
共享锁lockForShare
的锁加入在drop_lock
之中, 锁类型为读锁1
2
3
4
5
6
7
8
9TableLockHolder IStorage::lockForShare(const String & query_id, const std::chrono::milliseconds & acquire_timeout)
{
TableLockHolder result = tryLockTimed(drop_lock, RWLockImpl::Read, query_id, acquire_timeout);
if (is_dropped)
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
return result;
}
共享锁调用的地方非常多, 常见的Insert语句也是排它锁.
根据代码推论:
- 插入过程之中删除插入表, 删除动作会等待插入完成再执行
- 插入过程之中修改插入表, 表结构能够修改成功
- Insert语句锁住整个query执行时间
测试验证
建表语句
1 | CREATE TABLE `lineorder_local` |
插入语句
1 | ./clickhouse-client --query "INSERT INTO hzw.lineorder_local FORMAT CSV" < lineorder.tbl |
插入过程之中删除插入表
删除表语句1
drop table lineorder_local;
出现无法获取锁的问题
插入过程之中修改插入表
修改表语句
1
alter table lineorder_local drop column LO_QUANTITY;
执行后, 会立马成功
由于乱序执行, 测试一个更加夸张的例子
1
alter table lineorder_local delete where 1=1;
这里alter立马会成功, 数据会删除, 但是insert还在继续.