**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.
{
        case LogEntry::ATTACH_PART:
            
            [[fallthrough]];
        case LogEntry::GET_PART:
            return executeFetch(entry);
        case LogEntry::MERGE_PARTS:
            throw Exception(ErrorCodes::LOGICAL_ERROR, "Merge has to be executed by another function");
        case LogEntry::MUTATE_PART:
            throw Exception(ErrorCodes::LOGICAL_ERROR, "Mutation has to be executed by another function");
        case LogEntry::ALTER_METADATA:
            return executeMetadataAlter(entry);
        case LogEntry::SYNC_PINNED_PART_UUIDS:
            syncPinnedPartUUIDs();
            return true;
        case LogEntry::CLONE_PART_FROM_SHARD:
            executeClonePartFromShard(entry);
            return true;
        default:
            throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected log entry type: {}", static_cast<int>(entry.type));
    }
}
bool StorageReplicatedMergeTree::executeFetch(LogEntry & entry, bool need_to_check_missing_part)
{
    
    String replica = findReplicaHavingCoveringPart(entry, true);
    const auto storage_settings_ptr = getSettings();
    auto metadata_snapshot = getInMemoryMetadataPtr();
    try
    {