ClickHouse UPDATE 操作问题解决方案
问题背景
在使用ClickHouse进行数据更新操作时,遇到了以下错误:Lightweight updates are not supported
2025.09.24 11:08:51.283185 [ 70414 ] {09f4305c-14c5-4d63-a251-3179f5373d6d} <Error> executeQuery: Code: 48. DB::Exception: Lightweight updates are not supported. Lightweight updates are supported only for tables with materialized _block_offset column. Run 'MODIFY SETTING enable_block_offset_column = 1' command to enable it. (NOT_IMPLEMENTED) (version 25.8.2.29 (official build)) (from [::ffff:192.168.31.94]:53719) (in query: update ethereum.block_tasks set status = 'pending', owner = 'consumer-1_1758676754070328000', assigned_at = '2025-09-24 09:19:14.07', updated_at = '2025-09-24 09:19:14.07' WHERE start_block = ( SELECT start_block FROM ethereum.block_tasks WHERE (status = 'init' OR (status = 'pending' AND assigned_at < '2025-09-24 09:09:14.07')) AND (owner = '' OR owner IS NULL) ORDER BY start_block DESC LIMIT 1 )), Stack trace (when copying this message, always include the lines below):0. DB::Exception::Exception(DB::Exception::MessageMasked&&, int, bool) @ 0x00000000133a211f
1. DB::Exception::Exception(String&&, int, String, bool) @ 0x000000000c84f4ce
2. DB::Exception::Exception(PreformattedMessage&&, int) @ 0x000000000c84ef80
3. DB::Exception::Exception<String&>(int, FormatStringHelperImpl<std::type_identity<String&>::type>, String&) @ 0x000000000c86826b
4. DB::InterpreterUpdateQuery::execute() @ 0x00000000183d01b2
5. DB::executeQueryImpl(char const*, char const*, std::shared_ptr<DB::Context>, DB::QueryFlags, DB::QueryProcessingStage::Enum, std::unique_ptr<DB::ReadBuffer, std::default_delete<DB::ReadBuffer>>&, std::shared_ptr<DB::IAST>&, std::shared_ptr<DB::ImplicitTransactionControlExecutor>) @ 0x000000001832e352
6. DB::executeQuery(std::unique_ptr<DB::ReadBuffer, std::default_delete<DB::ReadBuffer>>, DB::WriteBuffer&, bool, std::shared_ptr<DB::Context>, std::function<void (DB::QueryResultDetails const&)>, DB::QueryFlags, std::optional<DB::FormatSettings> const&, std::function<void (DB::IOutputFormat&, String const&, std::shared_ptr<DB::Context const> const&, std::optional<DB::FormatSettings> const&)>, std::function<void ()>) @ 0x000000001833312a
7. DB::HTTPHandler::processQuery(DB::HTTPServerRequest&, DB::HTMLForm&, DB::HTTPServerResponse&, DB::HTTPHandler::Output&, std::optional<DB::CurrentThread::QueryScope>&, StrongTypedef<unsigned long, ProfileEvents::EventTag> const&) @ 0x0000000019940621
8. DB::HTTPHandler::handleRequest(DB::HTTPServerRequest&, DB::HTTPServerResponse&, StrongTypedef<unsigned long, ProfileEvents::EventTag> const&) @ 0x0000000019945224
9. DB::HTTPServerConnection::run() @ 0x0000000019a16760
10. Poco::Net::TCPServerConnection::start() @ 0x000000001ef1e687
11. Poco::Net::TCPServerDispatcher::run() @ 0x000000001ef1eb19
12. Poco::PooledThread::run() @ 0x000000001eee5147
13. Poco::ThreadImpl::runnableEntry(void*) @ 0x000000001eee3541
14. ? @ 0x0000000000094ac3
15. ? @ 0x0000000000125a04
解决方案
在创建表时添加以下设置即可解决:
CREATE TABLE block_tasks (-- 表结构定义
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(toDateTime(created_at))
PRIMARY KEY (start_block, end_block)
ORDER BY (start_block, end_block)
SETTINGS enable_block_number_column = 1, enable_block_offset_column = 1;
GORM代码示例:
err := db.Table(model.BlockTaskTableName).Set("gorm:table_options", "ENGINE = MergeTree() PARTITION BY toYYYYMM(toDateTime(created_at)) "+"PRIMARY KEY(start_block, end_block) "+"ORDER BY (start_block, end_block) "+"SETTINGS enable_block_number_column = 1, enable_block_offset_column = 1").AutoMigrate(&model.BlockTask{})
设置参数说明
enable_block_number_column = 1
:启用内部块编号列,支持轻量级更新机制enable_block_offset_column = 1
:启用块偏移列,提供更精确的数据定位
总结
通过设置 enable_block_number_column = 1
和 enable_block_offset_column = 1
,可以启用ClickHouse的轻量级更新机制,解决UPDATE操作的问题。