如何轻松取消Excel中的分页提升数据展示效果
2576
2022-05-29
问题现象
使用drop table system.query_log sync时,发现客户端一直卡住,长时间无法恢复。日志打印如下:
DatabaseCatalog: Waiting for table bd5888b9-a84c-41a8-bc7e-cefadf81cc43 to be finally dropped
进一步试验发现,如果我在卡住期间通过http连接后执行新的sql,卡住的命令就能正常执行了。但是,如果没有新的sql执行,会一直卡住。
问题分析
1、先了解下drop table xxx sync的流程。
# drop table system.query_log sync InterpreterDropQuery::execute executeToTable executeToTableImpl checkTableCanBeDropped StorageMergeTree::shutdown DatabaseAtomic::dropTable detachTableUnlocked tryRemoveSymlink enqueueDroppedTableCleanup if no delay tables_marked_dropped.push_front // 放在list的开头 else tables_marked_dropped.push_back // 默认8min后删除 tables_marked_dropped_ids.insert // 在set中存入需要删除的表 (*drop_task)->schedule() // dropTableDataTask 在DatabaseCatalog::loadDatabases中初始化 if no delay // 有sync或者no delay或者database_atomic_wait_for_drop_and_detach_synchronously为true waitForTableToBeActuallyDroppedOrDetached // 等待table被实际删除 waitTableFinallyDropped // wait_table_finally_dropped.wait // wait_table_finally_dropped 被通知,且 tables_marked_dropped_ids 中没有此表 # drop table的后台线程 DatabaseCatalog::dropTableDataTask // 只有不再使用且drop时间早于当前时间的table,才能被删除 if table 可以被删 tables_marked_dropped.erase dropTableFinally StorageMergeTree::drop // 删数据 shutdown // 直接就return dropAllData // 真正开始删除了 clearPartsFromFilesystem // 文件系统 disk->removeRecursive // 磁盘 remove // 删元数据 removeUUIDMappingFinally // 删uuid映射 tables_marked_dropped_ids.erase wait_table_finally_dropped.notify_all() // 通知不再wait if 还有表需要被删 dropTableDataTask // 继续删表,否则不再调度
从流程上可以知道:
(1)如果不加sync(即no delay),则默认是至少8min后才会真正删除数据。而在添加了sync后,则将需要删除的表放在list的开头,也不用等待8min。
(2)drop的主流程,也不会真正删除表,而是存入一个tables_marked_dropped中,由后台线程dropTableDataTask来操刀。如果设置了sync,drop的主流程,会等待后台线程的通知,然后才会返回客户端删除成功。
(3)真正删除时,需要保证该table没有流程在使用,通过查看该table的shared_ptr是否是unique来确定。
(4)每次只会删除一张表。如果还有待删除的表,则会继续,不需再等待。如果没有表需要删除,则不在触发此任务。
(5)每次执行完drop table后,其实都会触发query_log的记录,进而重建该表,因此,删除query_log是没有意义的。
2、再了解下query_log的流程
# query_log的机制 # query_log建立过程 Server::main global_context->initializeSystemLogs SystemLogs::SystemLogs // 初始化各个system log,包括query log createSystemLog // 根据config中的配置生成 SystemLog
这里比较特别的地方是:
(1)query_log在有log记录的时候,如果发现没有表的话,会走创建表的流程。如果已经有表了,则会比较列的结构是否一致,不一致的话,需要重建表,并将旧表重命名。
(2)如果在config.xml中修改表级的TTL,即使重启server,query_log也是不会变化的,因为已经存在该表,且表的列信息是一样的。如要让它生效,则需要删除query_log(会自动重建),或者采用ALTER TABLE的方式。这也是为什么第一次在config.xml中配置query_log时可以生效,而后续修改或者配置时又无法生效的原因。
3、问题分析
结合删除表时会卡住的时候报错以及正常流程时应该要有的日志(Removing metadata {} of dropped table),可知,是在dropTableDataTask中判断table是否没有地方在使用时出现了问题。
auto it = std::find_if(tables_marked_dropped.begin(), tables_marked_dropped.end(), [&](const auto & elem) { bool not_in_use = !elem.table || elem.table.unique(); bool old_enough = elem.drop_time <= current_time; min_drop_time = std::min(min_drop_time, elem.drop_time); tables_in_use_count += !not_in_use; return not_in_use && old_enough; });
即elem.table.unique()不满足。
然后,梳理整个流程和现象(在卡住期间通过http连接后执行新的sql,卡住的命令就能正常执行了)可以推理出,应该去看添加新log的流程。
template
在prepareTable中,得到了table的副本,而且一直没有释放,elem.table.unique()就一直无法满足。只有在新添加日志的时候,table变量被覆盖,原来的query_log的智能指针就被释放了,从而卡住的流程可以继续。
ClickHouse
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。