Симметричное управление версиями схемы DS

У меня есть сервер и несколько клиентов с базами данных, синхронизированными Simmetric-DS. Теперь версия базы данных 1.0 для клиента и сервера. Таким образом, столбец node.schema_version равен 1,0 для клиентов и сервера.

Я могу вручную обновить базу данных сервера до версии 2.0. Клиентские базы данных автоматически обновятся до версии 2.0 с помощью другого приложения.

Я хочу использовать node.schema_version, чтобы избежать синхронизации между сервером и узлами с версией, отличной от 2.0.

Я использовал маршрутизатор subselect с этим router_expression:

'(SELECT check_version(c.schema_version))'

.. где функция check_version имеет значение true, если версии клиента и сервера совпадают, в противном случае вызывает исключение для остановки синхронизации:

CREATE OR REPLACE FUNCTION check_version(v_ver_check text)
  RETURNS boolean AS
$BODY$
DECLARE
    v_ver_cur text;
    v_success boolean;
BEGIN
    v_success:=false;

    v_ver_cur:='';
    SELECT n.schema_version 
    FROM sym_node n 
      INNER JOIN sym_node_identity ni on n.node_id=ni.node_id
    INTO v_ver_cur;


    IF v_ver_cur=v_ver_check 
    THEN 
      v_success:=true;
    ELSE 
      RAISE EXCEPTION 'SERVER-DB-VERSION<>CLIENT-DB-VERSION';
    END IF;

    RETURN v_success;   
END;
$BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 1;

В случае несоответствия версии:

  • Во время загрузки данных с клиента на сервер:
    Этот подход работает нормально, поскольку исключение блокирует процесс синхронизации ТОЛЬКО на клиенте.

  • Во время загрузки данных с сервера на клиент: Исключение блокирует процесс синхронизации НА СЕРВЕРЕ, поэтому синхронизация блокируется для ВСЕХ клиентов.

Как я могу заблокировать процесс загрузки только против узла с version=1.0?


person Mario Di Ruscio    schedule 10.04.2015    source источник


Ответы (2)


Не уверен, что понимаю вопрос. В любом случае вы можете упростить функцию plpgsql:

CREATE OR REPLACE FUNCTION check_version(v_ver_check text)
  RETURNS boolean AS
$BODY$
BEGIN
   IF EXISTS ( 
      SELECT 1
      FROM   sym_node n 
      JOIN   sym_node_identity ni USING (node_id)
      WHERE  n.schema_version = v_ver_check
      ) THEN
      RETURN true;
   ELSE 
      RAISE EXCEPTION 'SERVER-DB-VERSION <> CLIENT-DB-VERSION';
   END IF;
END
$func$ LANGUAGE plpgsql STRICT;

Здесь есть немного догадок. О необходимой информации о задействованных таблицах речи не идет.

Интересно, почему на sym_node_identity нет условия WHERE? У sym_node и sym_node_identity есть только одна строка, совпадающая с node_id?

person Erwin Brandstetter    schedule 15.04.2015

Sym_node_identity будет иметь только одну строку, представляющую идентификатор узла, подключенного к данной базе данных, поэтому нет необходимости в предложении where для присоединения к одной строке в sym_node. Sym_node будет представлять узлы, с которыми взаимодействует текущий узел.

Однако я думаю, что вы можете полностью избавиться от функции check_version и использовать следующий запрос напрямую в выражении маршрутизатора. Выражение маршрутизатора подвыборки добавляет его к предложению where, чтобы определить, к каким спискам узлов следует направлять данные. В этом случае вы получаете версию для собственного узла (sym_node_identity) и получаете все остальные идентификаторы node_id в sym_node, которые имеют совпадающую версию. Обратите внимание, что это позволит вам синхронизировать только совпадающие версии, вы можете сделать >= вместо = в самом внутреннем запросе, если хотите, чтобы 1 синхронизировались с 2, но не наоборот.

c.node_id in (
    select node_id 
    from sym_node sn1
    join (
        select schema_version 
        from sym_node sn2
        join sym_node_identity si on si.node_id = sn2.node_id
    ) sv on sv.schema_version = sn1.schema_version
)
person Josh Hicks    schedule 21.04.2015