SQL Server: эквивалент RowVersion в Oracle

Имеет ли Oracle тип данных, аналогичный типу SQL Server?RowVersion?

Когда вы вставляете или обновляете строку, соответствующий столбец Версия (который имеет тип RowVersion) обновляется автоматически.

MSDN говорит о RowVersion:

  • Тип данных, который предоставляет автоматически генерируемые уникальные двоичные числа в базе данных. rowversion, как правило, используется в качестве механизма для строк таблицы версий. Размер хранилища составляет 8 байт. Тип данных rowversion является просто инкрементным числом и не сохраняет дату или время.

  • У каждой базы данных есть счетчик, который увеличивается на единицу для каждой операции вставки или обновления, выполняемой для таблицы, содержащей столбец версии строки в базе данных. Этот счетчик является версией строки базы данных. Это отслеживает относительное время в базе данных, а не фактическое время, которое может быть связано с часами. Таблица может иметь только один столбец версий строк. Каждый раз, когда строка со столбцом версии строки изменяется или вставляется, увеличенное значение строки базы данных вставляется в столбец версии строки.

  • Вы можете использовать столбец rowversion строки, чтобы легко определить, изменилось ли какое-либо значение в строке с момента последнего чтения. Если в строку вносятся какие-либо изменения, значение версии строки обновляется. Если в строку не было внесено никаких изменений, значение rowversion будет таким же, как и при предыдущем прочтении.

  • Вы можете добавить столбец версии строки в таблицу, чтобы помочь сохранить целостность базы данных, когда несколько пользователей обновляют строки одновременно. Вы также можете узнать, сколько строк и какие строки были обновлены, без повторного запроса к таблице.

Мы разрабатываем модель данных с помощью Oracle и хотели бы использовать колонку Version для управления параллелизмом.

Я также хотел бы знать, есть ли лучший путь в мире Oracle.

3 ответа

Решение

Простой ответ - нет, но его легко создать самостоятельно с помощью столбца NUMBER и триггера для его установки / обновления.

Простой пример для Oracle 11gR2:

CREATE SEQUENCE global_rowversion_seq;

ALTER TABLE mytable1 ADD rowversion NUMBER;

ALTER TABLE mytable2 ADD rowversion NUMBER;

CREATE TRIGGER mytable1_biu
   BEFORE INSERT OR UPDATE
   ON mytable1
   FOR EACH ROW
BEGIN
  :NEW.rowversion := global_rowversion_seq.NEXTVAL;
END mytable1_biu;

CREATE TRIGGER mytable2_biu
  BEFORE INSERT OR UPDATE
  ON mytable2
  FOR EACH ROW
BEGIN
  :NEW.rowversion := global_rowversion_seq.NEXTVAL;
END mytable2_biu;

(Если вы используете более раннюю версию Oracle, назначения в триггерах должны выполняться с помощью запроса, например:

  SELECT global_rowversion_seq.NEXTVAL
  INTO :NEW.rowversion
  FROM dual;

Теперь имейте в виду, что в некоторых случаях этот дизайн может оказывать влияние на производительность в экстремальных ситуациях (например, базы данных с очень высокой активностью вставки / обновления) из-за конкуренции со всеми вставками / обновлениями базы данных, использующими ту же последовательность. Конечно, в этих обстоятельствах вы, во всяком случае, могли бы избежать триггеров.

В зависимости от того, как вы используете столбец версии строки, может быть хорошей идеей использовать отдельную последовательность для каждой таблицы. Это, конечно, будет означать, что версия строки больше не будет глобально уникальной, но если вас интересует только сравнение изменений строк в таблице, это будет хорошо.

Другой подход состоит в том, чтобы увеличивать счетчик для каждой строки в отдельности - для этого не требуется последовательность и она позволяет обнаруживать изменения в строке (но не позволяет сравнивать какую-либо строку с другой строкой):

ALTER TABLE mytable ADD rowversion NUMBER;

CREATE TRIGGER mytable_biu
  BEFORE INSERT OR UPDATE
  ON mytable
  FOR EACH ROW
BEGIN
  :NEW.rowversion := NVL(:OLD.rowversion, 0) + 1;
END mytable_biu;

Каждая строка будет вставлена ​​с rowversion = 1, затем последующие обновления этой строки увеличат ее до 2, 3 и т. Д.

У Oracle есть SCN (номера изменений системы): http://docs.oracle.com/cd/E11882_01/server.112/e10713/transact.htm

Системный номер изменения (SCN) - это логическая внутренняя временная метка, используемая базой данных Oracle. SCN заказывает события, происходящие в базе данных, что необходимо для удовлетворения свойств ACID транзакции. Oracle Database использует SCN, чтобы пометить SCN, перед которым все изменения, как известно, находятся на диске, чтобы при восстановлении избежать ненужного повторного выполнения. База данных также использует SCN для обозначения точки, в которой не существует повторов для набора данных, чтобы можно было остановить восстановление.

SCN встречаются в монотонно возрастающей последовательности. Oracle Database может использовать SCN как часы, потому что наблюдаемый SCN указывает логический момент времени, а повторные наблюдения возвращают равные или большие значения. Если одно событие имеет более низкий SCN, чем другое событие, то это произошло раньше в отношении базы данных. Несколько событий могут использовать один и тот же SCN, что означает, что они произошли одновременно по отношению к базе данных.

Каждая транзакция имеет SCN. Например, если транзакция обновляет строку, база данных записывает SCN, в котором произошло это обновление. Другие модификации в этой транзакции имеют тот же SCN. Когда транзакция фиксируется, база данных записывает SCN для этой фиксации.


Используйте псевдостолбец ORA_ROWSCN для проверки текущего SCN строк:
http://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns007.htm

Пример:

SELECT ora_rowscn, t.* From test t;

Демо -> http://www.sqlfiddle.com/
(В SQLFiddle явные коммиты явно не работают - в реальной базе данных каждый коммит увеличивает SCN).


Пример на "реальной" базе данных:

CREATE TABLE test(
  id int,
  value int
);

INSERT INTO test VALUES(1,0);
COMMIT;
SELECT ora_rowscn, t.* FROM test t;

ORA_ROWSCN         ID      VALUE
---------- ---------- ----------
   3160728          1          0

UPDATE test SET value = value + 1 WHERE id = 1;
COMMIT;
SELECT ora_rowscn, t.* FROM test t;

ORA_ROWSCN         ID      VALUE
---------- ---------- ----------
   3161657          1          1

UPDATE test SET value = value + 1 WHERE id = 1;
COMMIT;
SELECT ora_rowscn, t.* FROM test t;

ORA_ROWSCN         ID      VALUE
---------- ---------- ----------
   3161695          1          2 

Если SCN транзакции известен, мы можем использовать ретроспективный запрос для получения прошлого значения строки:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_flashback.htm

Пример:

SELECT t.*,
       versions_startscn, versions_starttime,
       versions_endscn, versions_endtime,
       versions_xid, versions_operation
FROM test VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE t;

        ID      VALUE VERSIONS_STARTSCN VERSIONS_STARTTIME  VERSIONS_ENDSCN VERSIONS_ENDTIME    VERSIONS_XID     VERSIONS_OPERATION
---------- ---------- ----------------- ------------------- --------------- ------------------- ---------------- ------------------
         1          2           3161695 13/12/10 08:19:39                                       06000300EA070000 U                  
         1          1           3161657 13/12/10 08:18:39           3161695 13/12/10 08:19:39   06001200EA070000 U                  
         1          0                                               3161657 13/12/10 08:18:39                         


SELECT t.*,
       versions_startscn, versions_starttime,
       versions_endscn, versions_endtime,
       versions_xid, versions_operation
FROM test VERSIONS BETWEEN SCN 3161657 AND 3161657 t;

        ID      VALUE VERSIONS_STARTSCN VERSIONS_STARTTIME  VERSIONS_ENDSCN VERSIONS_ENDTIME    VERSIONS_XID     VERSIONS_OPERATION
---------- ---------- ----------------- ------------------- --------------- ------------------- ---------------- ------------------
         1          1           3161657 13/12/10 08:18:39                                       06001200EA070000 U                               

Согласно документации Oracle, вы можете использовать ORA_ROWSCN и "ROWDEPENDENCIES" для отслеживания зависимостей на уровне строк. не на физический блок данных.

Ссылка: https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm

http://www.dba-oracle.com/t_row_scn_rowdependencies.htm

Другие вопросы по тегам