**Describe the solution you'd like**

We already can run clickhouse-server without configured ZooKeeper (the tables will start in read-only mode)
and with configured ZooKeeper, if it starts to be inaccessible at runtime (the tables will be read-only until the session is re-established).

Let's also make it possible to start up when ZooKeeper is unavailable.

**Additional context**

If that will be very hard to implement, we can consider other options:
- lazy attaching of the tables after sever start-up;
- a maintenance mode when the tables are not attached at start-up and require manual ATTACH queries.
return false;
            if (select_decision != SelectPartsDecision::SELECTED)
            {
                constexpr const char * message_fmt = "Cannot select parts for optimization: {}";
                assert(disable_reason != unknown_disable_reason);
                if (!partition_id.empty())
                    disable_reason += fmt::format(" (in partition {})", partition_id);
                String message = fmt::format(message_fmt, disable_reason);
                LOG_INFO(log, fmt::runtime(message));
                return handle_noop(message);
            }
            ReplicatedMergeTreeLogEntryData merge_entry;
            CreateMergeEntryResult create_result = createLogEntryToMergeParts(
                zookeeper, future_merged_part->parts,
                future_merged_part->name, future_merged_part->uuid, future_merged_part->type,
                deduplicate, deduplicate_by_columns,
                &merge_entry, can_merge.getVersion(), future_merged_part->merge_type);
            if (create_result == CreateMergeEntryResult::MissingPart)
            {
                String message = "Can't create merge queue node in ZooKeeper, because some parts are missing";
                LOG_TRACE(log, fmt::runtime(message));
                return handle_noop(message);
            }
            if (create_result == CreateMergeEntryResult::LogUpdated)
                continue;
            merge_entries.push_back(std::move(merge_entry));
            return true;
        }
        assert(try_no == max_retries);
        String message = fmt::format("Can't create merge queue node in ZooKeeper, because log was updated in every of {} tries", try_no);