From 82a87bc0d2dd84afc32da7efd97e60f36134708b Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 7 Apr 2020 18:28:29 +0300 Subject: [PATCH] Fix replicated tables startup when updating from old version --- src/Storages/StorageReplicatedMergeTree.cpp | 16 +++++- .../test_no_local_metadata_node/__init__.py | 0 .../test_no_local_metadata_node/test.py | 54 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/integration/test_no_local_metadata_node/__init__.py create mode 100644 tests/integration/test_no_local_metadata_node/test.py diff --git a/src/Storages/StorageReplicatedMergeTree.cpp b/src/Storages/StorageReplicatedMergeTree.cpp index 7107328e4ff..2f598630f65 100644 --- a/src/Storages/StorageReplicatedMergeTree.cpp +++ b/src/Storages/StorageReplicatedMergeTree.cpp @@ -256,6 +256,15 @@ StorageReplicatedMergeTree::StorageReplicatedMergeTree( } else { + /// In old tables this node may missing + String replica_metadata; + bool replica_metadata_exists = current_zookeeper->tryGet(replica_path + "/metadata", replica_metadata); + if (!replica_metadata_exists || replica_metadata.empty()) + { + ReplicatedMergeTreeTableMetadata current_metadata(*this); + current_zookeeper->createOrUpdate(replica_path + "/metadata", current_metadata.toString(), zkutil::CreateMode::Persistent); + } + checkTableStructure(replica_path); checkParts(skip_sanity_checks); @@ -263,8 +272,13 @@ StorageReplicatedMergeTree::StorageReplicatedMergeTree( { metadata_version = parse(current_zookeeper->get(replica_path + "/metadata_version")); } - else /// This replica was created on old version, so we have to take version of global node + else { + /// This replica was created with old clickhouse version, so we have + /// to take version of global node. If somebody will alter our + /// table, than we will fill /metadata_version node in zookeeper. + /// Otherwise on the next restart we can again use version from + /// shared metadata node because it was not changed. Coordination::Stat metadata_stat; current_zookeeper->get(zookeeper_path + "/metadata", &metadata_stat); metadata_version = metadata_stat.version; diff --git a/tests/integration/test_no_local_metadata_node/__init__.py b/tests/integration/test_no_local_metadata_node/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_no_local_metadata_node/test.py b/tests/integration/test_no_local_metadata_node/test.py new file mode 100644 index 00000000000..ef240cd710c --- /dev/null +++ b/tests/integration/test_no_local_metadata_node/test.py @@ -0,0 +1,54 @@ +import time +import pytest + +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', with_zookeeper=True) + +@pytest.fixture(scope="module") +def start_cluster(): + try: + cluster.start() + + yield cluster + finally: + cluster.shutdown() + + +def test_table_start_without_metadata(start_cluster): + node1.query(""" + CREATE TABLE test (date Date) + ENGINE = ReplicatedMergeTree('/clickhouse/table/test_table', '1') + ORDER BY tuple() + """) + + node1.query("INSERT INTO test VALUES(toDate('2019-12-01'))") + + assert node1.query("SELECT date FROM test") == "2019-12-01\n" + + # some fake alter + node1.query("ALTER TABLE test MODIFY COLUMN date Date DEFAULT toDate('2019-10-01')") + + assert node1.query("SELECT date FROM test") == "2019-12-01\n" + + node1.query("DETACH TABLE test") + zk_cli = cluster.get_kazoo_client('zoo1') + + # simulate update from old version + zk_cli.delete("/clickhouse/table/test_table/replicas/1/metadata") + zk_cli.delete("/clickhouse/table/test_table/replicas/1/metadata_version") + + node1.query("ATTACH TABLE test") + + assert node1.query("SELECT date FROM test") == "2019-12-01\n" + + node1.query("ALTER TABLE test MODIFY COLUMN date Date DEFAULT toDate('2019-09-01')") + + node1.query("DETACH TABLE test") + + zk_cli.set("/clickhouse/table/test_table/replicas/1/metadata", "") + + node1.query("ATTACH TABLE test") + + assert node1.query("SELECT date FROM test") == "2019-12-01\n"