Fixed race condition in DROP/CREATE MergeTree tables [#CLICKHOUSE-3939]

This commit is contained in:
Alexey Milovidov 2018-09-07 04:39:48 +03:00
parent 836bf136e3
commit 199d8734f9
5 changed files with 38 additions and 4 deletions

View File

@ -82,7 +82,6 @@ public:
~QueryScope();
};
public:
/// Implicitly finalizes current thread in the destructor
class ThreadScope
{

View File

@ -576,9 +576,18 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
context.getSessionContext().addExternalTable(table_name, res, query_ptr);
else
database->createTable(context, table_name, res, query_ptr);
}
res->startup();
/// We must call "startup" and "shutdown" while holding DDLGuard.
/// Because otherwise method "shutdown" (from InterpreterDropQuery) can be called before startup
/// (in case when table was created and instantly dropped before started up)
///
/// Method "startup" may create background tasks and method "shutdown" will wait for them.
/// But if "shutdown" is called before "startup", it will exit early, because there are no background tasks to wait.
/// Then background task is created by "startup" method. And when destructor of a table object is called, background task is still active,
/// and the task will use references to freed data.
res->startup();
}
/// If the query is a CREATE SELECT, insert the data into the table.
if (create.select && !create.attach

View File

@ -208,7 +208,7 @@ DatabaseAndTable InterpreterDropQuery::tryGetDatabaseAndTable(String & database_
throw Exception("Table " + backQuoteIfNeed(database_name) + "." + backQuoteIfNeed(table_name) + " doesn't exist.",
ErrorCodes::UNKNOWN_TABLE);
return std::make_pair<DatabasePtr, StoragePtr>(std::move(database), std::move(table));
return {std::move(database), std::move(table)};
}
return {};
}

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -e
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
. $CURDIR/../shell_config.sh
function stress()
{
while true; do
${CLICKHOUSE_CLIENT} --query "CREATE TABLE IF NOT EXISTS test.table (x UInt8) ENGINE = MergeTree ORDER BY tuple()" 2>/dev/null
${CLICKHOUSE_CLIENT} --query "DROP TABLE test.table" 2>/dev/null
done
}
# https://stackoverflow.com/questions/9954794/execute-a-shell-function-with-timeout
export -f stress
for thread in {1..5}; do
timeout 10 bash -c stress &
done
wait
echo
${CLICKHOUSE_CLIENT} --query "DROP TABLE IF EXISTS test.table";