rewrite static StorageReplicatedMergeTree::dropReplica

This commit is contained in:
amudong 2020-06-22 23:01:40 +08:00
parent 7723dc4935
commit 0101947403
3 changed files with 55 additions and 52 deletions

View File

@ -405,6 +405,9 @@ void InterpreterSystemQuery::restartReplicas(Context & system_context)
void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query)
{
StorageReplicatedMergeTree::Status status;
auto zookeeper = context.getZooKeeper();
if (!table_id.empty())
{
context.checkAccess(AccessType::SYSTEM_DROP_REPLICA, table_id);
@ -412,7 +415,10 @@ void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query)
if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(table.get()))
{
storage_replicated->dropReplica(query.replica, false);
storage_replicated->getStatus(status);
if (query.replica == status.replica_name)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica", ErrorCodes::LOGICAL_ERROR);
storage_replicated->dropReplica(zookeeper, status.zookeeper_path, query.replica, status.is_readonly ,false);
LOG_TRACE(log, "DROP REPLICA " + table_id.getNameForLogs() + " [" + query.replica + "]: OK");
}
else
@ -428,7 +434,10 @@ void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query)
if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(iterator->table().get()))
{
context.checkAccess(AccessType::SYSTEM_DROP_REPLICA, iterator->table()->getStorageID());
storage_replicated->dropReplica(query.replica, false);
storage_replicated->getStatus(status);
if (query.replica == status.replica_name)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica", ErrorCodes::LOGICAL_ERROR);
storage_replicated->dropReplica(zookeeper, status.zookeeper_path, query.replica, status.is_readonly ,false);
}
}
LOG_TRACE(log, "DROP REPLICA " + query.replica + " DATABSE " + database->getDatabaseName() + ": OK");
@ -438,7 +447,36 @@ void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query)
}
else if (!query.replica_zk_path.empty())
{
StorageReplicatedMergeTree::dropReplicaByZkPath(context, query.replica_zk_path, query.replica);
auto remote_replica_path = query.replica_zk_path + "/replicas/" + query.replica;
auto & catalog = DatabaseCatalog::instance();
for (auto & elem : catalog.getDatabases())
{
DatabasePtr & database = elem.second;
for (auto iterator = database->getTablesIterator(context); iterator->isValid(); iterator->next())
{
if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(iterator->table().get()))
{
storage_replicated->getStatus(status);
if (status.replica_path.compare(remote_replica_path) == 0)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica",
ErrorCodes::LOGICAL_ERROR);
if (status.replica_path.compare(query.replica_zk_path + "/replicas/" + status.replica_name) == 0)
{
storage_replicated->dropReplica(zookeeper, query.replica_zk_path, query.replica, status.is_readonly ,false);
return;
}
}
}
}
/// It may left some garbage if replica_path subtree are concurently modified
/// check if is active replica if we drop other replicas
if (zookeeper->exists(remote_replica_path + "/is_active"))
throw Exception("Can't remove replica: " + query.replica + ", because it's active",
ErrorCodes::LOGICAL_ERROR);
zookeeper->tryRemoveRecursive(remote_replica_path);
LOG_INFO(log, "Removing replica {}", query.replica_zk_path + "/replicas/" + query.replica);
}
else if (query.is_drop_whole_replica)
@ -453,7 +491,10 @@ void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query)
if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(iterator->table().get()))
{
context.checkAccess(AccessType::SYSTEM_DROP_REPLICA, iterator->table()->getStorageID());
storage_replicated->dropReplica(query.replica, false);
storage_replicated->getStatus(status);
if (query.replica == status.replica_name)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica", ErrorCodes::LOGICAL_ERROR);
storage_replicated->dropReplica(zookeeper, status.zookeeper_path, query.replica, status.is_readonly ,false);
}
}
LOG_TRACE(log, "DROP REPLICA " + query.replica + " DATABSE " + database->getDatabaseName() + ": OK");

View File

@ -620,15 +620,19 @@ void StorageReplicatedMergeTree::createReplica()
void StorageReplicatedMergeTree::drop()
{
/// There is also the case when user has configured ClickHouse to wrong ZooKeeper cluster,
/// in this case, has_metadata_in_zookeeper = false, and we also permit to drop the table.
if (has_metadata_in_zookeeper)
{
auto zookeeper = tryGetZooKeeper();
/// If probably there is metadata in ZooKeeper, we don't allow to drop the table.
if (is_readonly || !zookeeper)
throw Exception("Can't drop readonly replicated table (need to drop data in ZooKeeper as well)", ErrorCodes::TABLE_IS_READ_ONLY);
shutdown();
dropReplica(replica_name, true);
dropReplica(zookeeper, zookeeper_path, replica_name, is_readonly ,true);
}
dropAllData();
@ -746,10 +750,11 @@ static time_t tryGetPartCreateTime(zkutil::ZooKeeperPtr & zookeeper, const Strin
return res;
}
void StorageReplicatedMergeTree::dropReplica(const String & replica, bool is_drop_table)
void StorageReplicatedMergeTree::dropReplica(zkutil::ZooKeeperPtr zookeeper, const String & zookeeper_path, const String & replica, bool is_readonly, bool is_drop_table)
{
auto zookeeper = tryGetZooKeeper();
static Poco::Logger * log = &Poco::Logger::get("StorageReplicatedMergeTree::dropReplica");
/// If probably there is metadata in ZooKeeper, we don't allow to drop the table.
if (is_readonly || !zookeeper)
throw Exception("Can't drop readonly replicated table (need to drop data in ZooKeeper as well)", ErrorCodes::TABLE_IS_READ_ONLY);
@ -758,8 +763,6 @@ void StorageReplicatedMergeTree::dropReplica(const String & replica, bool is_dro
if (!is_drop_table)
{
if (replica == replica_name)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica", ErrorCodes::LOGICAL_ERROR);
if (zookeeper->exists(zookeeper_path + "/replicas/" + replica + "/is_active"))
throw Exception("Can't drop replica: " + replica + ", because it's active",
ErrorCodes::LOGICAL_ERROR);
@ -849,43 +852,6 @@ void StorageReplicatedMergeTree::dropReplica(const String & replica, bool is_dro
}
}
void StorageReplicatedMergeTree::dropReplicaByZkPath(Context & context, const String & replica_zk_path, const String & replica)
{
auto remote_replica_path = replica_zk_path + "/replicas/" + replica;
auto & catalog = DatabaseCatalog::instance();
StorageReplicatedMergeTree::Status status;
for (auto & elem : catalog.getDatabases())
{
DatabasePtr & database = elem.second;
for (auto iterator = database->getTablesIterator(context); iterator->isValid(); iterator->next())
{
if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(iterator->table().get()))
{
storage_replicated->getStatus(status);
if (status.replica_path.compare(remote_replica_path) == 0)
throw Exception("We can't drop local replica, please use `DROP TABLE` if you want to clean the data and drop this replica",
ErrorCodes::LOGICAL_ERROR);
if (status.replica_path.compare(replica_zk_path + "/replicas/" + status.replica_name) == 0)
{
storage_replicated->dropReplica(replica, false);
return;
}
}
}
}
/// It may left some garbage if replica_path subtree are concurently modified
auto zookeeper = context.getZooKeeper();
//check if is active replica if we drop other replicas
if (zookeeper->exists(remote_replica_path + "/is_active"))
throw Exception("Can't remove replica: " + replica + ", because it's active",
ErrorCodes::LOGICAL_ERROR);
zookeeper->tryRemoveRecursive(remote_replica_path);
}
void StorageReplicatedMergeTree::checkParts(bool skip_sanity_checks)
{
auto zookeeper = getZooKeeper();

View File

@ -117,10 +117,6 @@ public:
void truncate(const ASTPtr &, const Context &, TableStructureWriteLockHolder &) override;
/** Remove a specific replica from zookeeper.
*/
void dropReplica(const String & replica, bool is_drop_table);
void rename(const String & new_path_to_table_data, const StorageID & new_table_id) override;
bool supportsIndexForIn() const override { return true; }
@ -184,9 +180,9 @@ public:
int getMetadataVersion() const { return metadata_version; }
/** Remove a specific replica from zookeeper by zkpath.
/** Remove a specific replica from zookeeper.
*/
static void dropReplicaByZkPath(Context & context, const String & replica_zk_path, const String & replica);
static void dropReplica(zkutil::ZooKeeperPtr zookeeper, const String & zookeeper_path, const String & replica, bool is_readonly, bool is_drop_table);
private: