mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-11 01:54:55 +00:00
Allowed concurrent CREATE TABLE IF NOT EXISTS if table exists [#METR-20704].
This commit is contained in:
parent
60252fed27
commit
1f8f6fa06a
@ -165,6 +165,8 @@ public:
|
||||
/// Получить объект, который защищает таблицу от одновременного выполнения нескольких DDL операций.
|
||||
/// Если такой объект уже есть - кидается исключение.
|
||||
std::unique_ptr<DDLGuard> getDDLGuard(const String & database, const String & table, const String & message) const;
|
||||
/// Если таблица уже есть - возвращается nullptr, иначе создаётся guard.
|
||||
std::unique_ptr<DDLGuard> getDDLGuardIfTableDoesntExist(const String & database, const String & table, const String & message) const;
|
||||
|
||||
String getCurrentDatabase() const;
|
||||
String getCurrentQueryId() const;
|
||||
|
@ -127,6 +127,7 @@ struct ContextShared
|
||||
/// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже.
|
||||
using DDLGuards = std::unordered_map<String, std::unordered_map<String, String>>;
|
||||
DDLGuards ddl_guards;
|
||||
/// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке.
|
||||
mutable std::mutex ddl_guards_mutex;
|
||||
|
||||
|
||||
@ -566,6 +567,18 @@ std::unique_ptr<DDLGuard> Context::getDDLGuard(const String & database, const St
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<DDLGuard> Context::getDDLGuardIfTableDoesntExist(const String & database, const String & table, const String & message) const
|
||||
{
|
||||
auto lock = getLock();
|
||||
|
||||
Databases::const_iterator it = shared->databases.find(database);
|
||||
if (shared->databases.end() != it && it->second->isTableExist(table))
|
||||
return {};
|
||||
|
||||
return getDDLGuard(database, table, message);
|
||||
}
|
||||
|
||||
|
||||
void Context::addDatabase(const String & database_name, const DatabasePtr & database)
|
||||
{
|
||||
auto lock = getLock();
|
||||
|
@ -487,12 +487,17 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
||||
|
||||
if (!create.is_temporary)
|
||||
{
|
||||
guard = context.getDDLGuard(database_name, table_name,
|
||||
"Table " + database_name + "." + table_name + " is creating or attaching right now");
|
||||
|
||||
context.assertDatabaseExists(database_name);
|
||||
|
||||
if (context.isTableExist(database_name, table_name))
|
||||
/** Если таблица уже существует, и в запросе указано IF NOT EXISTS,
|
||||
* то мы разрешаем конкуррентные запросы CREATE (которые ничего не делают).
|
||||
* Иначе конкуррентные запросы на создание таблицы, если таблицы не существует,
|
||||
* могут кидать исключение, даже если указано IF NOT EXISTS.
|
||||
*/
|
||||
guard = context.getDDLGuardIfTableDoesntExist(database_name, table_name,
|
||||
"Table " + database_name + "." + table_name + " is creating or attaching right now");
|
||||
|
||||
if (!guard)
|
||||
{
|
||||
if (create.if_not_exists)
|
||||
return {};
|
||||
|
Loading…
Reference in New Issue
Block a user