记录一次服务器异常重启,CK启动失败

生产的CK集群模式为4*2,即4个shard,其中每个shard有2个replica,采用复制表(Replicated)。

集群中一个CK节点,因服务器电压不稳意外重启后,CK启动失败,一直报错:

2021.12.23 15:14:17.461463 [ 2033 ] {} <Error> g*c.j*_local (8e95bb13-ec71-49cd-8e95-bb13ec71c9cd): Detaching broken part /data/clickhouse/store/8e9/8e95bb13-ec71-49cd-8e95-bb13ec71c9cd/20211223_5057_5057_0. If it happened after update, it is likely because of backward incompability. You need to resolve this manually
2021.12.23 15:14:17.623012 [ 2046 ] {} <Error> auto DB::MergeTreeData::loadDataParts(bool)::(anonymous class)::operator()() const: Code: 27. DB::ParsingException: Cannot parse input: expected 'columns format version: 1\n' at end of stream. (CANNOT_PARSE_INPUT_ASSERTION_FAILED), Stack trace (when copying this message, always include the lines below):

0. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool) @ 0x9366e7a in /usr/bin/clickhouse
1. DB::throwAtAssertionFailed(char const*, DB::ReadBuffer&) @ 0x93c1717 in /usr/bin/clickhouse
2. DB::NamesAndTypesList::readText(DB::ReadBuffer&) @ 0x1031c0f8 in /usr/bin/clickhouse
3. DB::IMergeTreeDataPart::loadColumns(bool) @ 0x1141a7bb in /usr/bin/clickhouse
4. DB::IMergeTreeDataPart::loadColumnsChecksumsIndexes(bool, bool) @ 0x11419c69 in /usr/bin/clickhouse
5. ? @ 0x114b827a in /usr/bin/clickhouse
6. ThreadPoolImpl<ThreadFromGlobalPool>::worker(std::__1::__list_iterator<ThreadFromGlobalPool, void*>) @ 0x93aabb8 in /usr/bin/clickhouse
7. ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'()::operator()() @ 0x93ac75f in /usr/bin/clickhouse
8. ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) @ 0x93a7e9f in /usr/bin/clickhouse
9. ? @ 0x93ab783 in /usr/bin/clickhouse
10. start_thread @ 0x7ea5 in /usr/lib64/libpthread-2.17.so
11. __clone @ 0xfe96d in /usr/lib64/libc-2.17.so
 (version 21.9.2.17 (official build))
2021.12.23 15:14:20.060892 [ 1869 ] {} <Error> Application: Caught exception while loading metadata: Code: 231. DB::Exception: Suspiciously many (15) broken parts to remove.: Cannot attach table `g*c`.`j*_local` from metadata file /data/clickhouse/store/d39/d39c2612-17b0-43e1-939c-261217b083e1/j*_local.sql from query ATTACH TABLE g*c.j*_local UUID 'f950b4dc-b0f6-4de8-b950-b4dcb0f6fde8' (...) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/g*c/j*_local', '{replica}') PARTITION BY toYYYYMMDD(data_time) ORDER BY (...) SETTINGS index_granularity = 8192: while loading database `g*c` from path /data/clickhouse/metadata/g*c. (TOO_MANY_UNEXPECTED_DATA_PARTS), Stack trace (when copying this message, always include the lines below):

0. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool) @ 0x9366e7a in /usr/bin/clickhouse
1. DB::MergeTreeData::loadDataParts(bool) @ 0x11465d60 in /usr/bin/clickhouse
2. DB::StorageReplicatedMergeTree::StorageReplicatedMergeTree(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, DB::StorageID const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, DB::StorageInMemoryMetadata const&, std::__1::shared_ptr<DB::Context>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, DB::MergeTreeData::MergingParams const&, std::__1::unique_ptr<DB::MergeTreeSettings, std::__1::default_delete<DB::MergeTreeSettings> >, bool, bool) @ 0x1119a498 in /usr/bin/clickhouse
3. ? @ 0x11687ba7 in /usr/bin/clickhouse
4. DB::StorageFactory::get(DB::ASTCreateQuery const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<DB::Context>, std::__1::shared_ptr<DB::Context>, DB::ColumnsDescription const&, DB::ConstraintsDescription const&, bool) const @ 0x11100f61 in /usr/bin/clickhouse
5. DB::createTableFromAST(DB::ASTCreateQuery, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<DB::Context>, bool) @ 0x105ed4c5 in /usr/bin/clickhouse
6. ? @ 0x105eb573 in /usr/bin/clickhouse
7. ? @ 0x105ec5ff in /usr/bin/clickhouse
8. ThreadPoolImpl<ThreadFromGlobalPool>::worker(std::__1::__list_iterator<ThreadFromGlobalPool, void*>) @ 0x93aabb8 in /usr/bin/clickhouse
9. ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'()::operator()() @ 0x93ac75f in /usr/bin/clickhouse
10. ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) @ 0x93a7e9f in /usr/bin/clickhouse
11. ? @ 0x93ab783 in /usr/bin/clickhouse
12. start_thread @ 0x7ea5 in /usr/lib64/libpthread-2.17.so
13. __clone @ 0xfe96d in /usr/lib64/libc-2.17.so
 (version 21.9.2.17 (official build))
总结一下报错关键字:
  • Detaching broken part
  • DB::Exception: Suspiciously many (15) broken parts to remove
  • DB::ParsingException: Cannot parse input: expected 'columns format version: 1\n' at end of stream
先直接放解决方案:

查找官方文档中,在Data Replication说明这里,提到了故障恢复方法:

  • 方法1:在ZooKeeper 中创建节点 /path_to_table/replica_name/flags/force_restore_data,节点值可以是任何内容。
    修改ZK是一个很有风险的操作,所以建议先尝试方法2。

  • 方法2: 运行以下命令:

sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data

注意这里flage目录可以是你安装时指定的具体clickhouse根目录。然后重启CK服务,CK会从另外一个备份中恢复数据。
这里是CK自带的故障恢复机制,前提是使用复制表(Replicated开头),本质是告诉CK,强制重建数据。建议使用此方法。

如果数据完全丢失的情况,进行restore时,CK本身没有带宽限制,表很多或数据量很大的话,需要做好网络压力以及时间评估。

问题分析:
  1. 在遇到错误后,我开始检查CK的数据文件目录,发现有以下情况:
ll -h /data/clickhouse/server/store/8e9/8e95bb13-ec71-49cd-8e95-bb13ec71c9cd/20211223_5057_5057_0
total 0
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 checksums.txt
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 columns.txt
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 count.txt
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 data.bin
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 data.mrk1
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 partition.dat
-rw-r----- 1 clickhouse clickhouse 0 Dec 23 16:32 primary.idx

目录下的所有文件都是空的(0B大小),原因无从得知,只能假定是因为服务器级别的异常重启,数据仍然在缓冲区中,没有写入磁盘?于是有了上面的“ParsingException”,CK没有读取到期望的值。

  1. 继续观察报错日志,发现错误日志开始于DB::MergeTreeData::loadDataParts(bool)方法,搜索一下源码中报错的位置
Detaching broken part
Suspiciously many broken parts to remove

得到CK的逻辑为:
启动时,检查本地文件系统中的数据集是否与预期的数据集( ZooKeeper 中信息)一致。如果存在轻微的不一致,系统会通过与副本同步数据来解决,如果系统检测到损坏的数据片段(如文件大小错误)或无法识别的片段(写入文件系统但未记录在 ZooKeeper 中的部分),则会把它们移动到 ‘detached’ 子目录(相当于逻辑删除),然后再从其他备份中去恢复这个数据片段。
但是注意这里是有一个安全机制的,即CK判断你损坏的片段大于一定的值(max_suspicious_broken_parts,对应源码图二中的逻辑),即“本地数据集与预期数据的差异太大”,CK将会拒绝帮你自动修复,并抛出异常、阻塞启动,这个时候你就必须手动执行恢复。

通过查询配置得到,max_suspicious_broken_parts参数的默认值是10:

SELECT *
FROM system.merge_tree_settings
WHERE name LIKE '%max_suspicious_broken_parts%'
max_suspicious_broken_parts

通过此次异常处理,更加深了CK“一辆性能超强的手动跑车”的印象,如同传说中的法拉利开启了ESC-OFF死亡模式,生死完全掌握在使用者的手上,不愧是战斗名族开源出来的系统。在完善周边支撑的道路上,CK还有很长的路要走。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容