2011-01-13 6 views
2

Это вопрос только для обсуждения. Прямо сейчас, мне нужно переконструировать таблицу базы данных mysql. В принципе, эта таблица содержит все записи контракта, которые я синхронизировал из другой базы данных. Запись договора может быть изменена, удалена или пользователи могут добавлять новые записи контракта через интерфейс графического интерфейса. На этом этапе структура таблицы точно такая же, как информация о контракте (столбец: серийный номер, дата истечения срока и т. Д.). В этом случае я могу только синхронизировать всю таблицу (удалить все старые записи, заменить их новыми). Если я хочу дельта (только синхронизировать с измененными, новыми, удаленными записями), синхронизировать таблицу, как мне изменить схему базы данных?Схема базы данных подходит для дельта-синхронизации

вот метод, который я придумал, но мне нужны ваши предложения, потому что я думаю, что это распространенный сценарий в приложениях баз данных. 1) ввести концепцию/столбец последовательности: для каждой последовательности отметьте новые добавленные записи, измененные записи, удаленные записи с этим порядковым номером. Записывая последний синхронизированный порядковый номер, передавайте только те записи с более высоким порядковым номером;

2) поскольку удаленные контракты могут быть добавлены обратно, а исходная таблица имеет ограничения первичного ключа, следует ли создать другую таблицу для этих удаленных записей? или добавить столбец флага, чтобы указать, был ли этот контракт удален?

Надеюсь, я ясно объясню свой вопрос. В любом случае, если вы знаете какие-либо статьи или свои собственные предложения об этом, сообщите мне. Благодаря!

ответ

8

Я думаю, вы смущены концепцией дельта.

Либо вы получаете полные нагрузки (весь набор данных), либо только изменения («дельта»).

Если вы имеете дело с полными нагрузками, вы можете сделать усечение + вставку. Таким образом вам не придется иметь дело с новыми или старыми строками или удалениями. Это может быть не представляется возможным из-за ограничений ссылочной целостности и т.д.

Если вы получаете дельту, каждая строка, как правило, положить в 1 из 2 категории:

  1. Matching ключ = UPDATE. Вы можете игнорировать строки с идентичными данными или перезаписывать.
  2. Нет соответствие ключа = INSERT

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

В случае дельта вы можете согласиться отправить строку с маркером удаления (флаг, дата). Затем вы можете решить, следует ли сохранить строку с маркером удаления (автоматически обрабатывается (1) выше), или если вы должны указать DELETE свою строку. Я предлагаю сохранить его, потому что рано или поздно кто-то будет обвинять вас в недостатках строк/плохих данных, а затем вы бросаете DELETE_DATE в их лицо.

Для MySQL вы можете использовать INSERT ... ON DUPLICATE KEY UPDATE для реализации функциональности «upsert».

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

Update:

Хорошо, вот пример.Скажите, что у вас есть следующие структуры таблицы:

create table contracts(
    contract_id int   not null 
    ,details1 varchar(20) 
    ,details2 varchar(20) 
    ,delete_date date 
    ,primary key(contract_id) 
); 

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

create table contracts_delta(
    contract_id int   not null 
    ,details1 varchar(20) 
    ,details2 varchar(20) 
    ,delete_date date 
    ,primary key(contract_id) 
); 

Некоторые примеры данных:

mysql> select * from contracts; 
+-------------+----------+----------+-------------+ 
| contract_id | details1 | details2 | delete_date | 
+-------------+----------+----------+-------------+ 
|   1 | a1  | a2  | NULL  | 
|   2 | b1  | b2  | NULL  | 
|   3 | c1  | c2  | 2011-01-03 | 
+-------------+----------+----------+-------------+ 

mysql> select * from contracts_delta; 
+-------------+----------+----------+-------------+ 
| contract_id | details1 | details2 | delete_date | 
+-------------+----------+----------+-------------+ 
|   2 | b1  | b2  | 2011-01-03 | <-- Row was deleted 
|   3 | c1  | c2  | NULL  | <-- No longer deleted 
|   4 | d1  | d2  | NULL  | <-- This is new row 
+-------------+----------+----------+-------------+ 

Используя синтаксис, связанный с предыдущим, вы можете вставить все новые строки. Всякий раз, когда строка уже существует (в двух экземплярах), мы решили обновить столбцы. Обратите внимание, что это обрабатывает удаленные строки автоматически, так как delete_date является регулярным столбцом, как и все остальное.

insert 
    into contracts(
     contract_id 
     ,details1 
     ,details2 
     ,delete_date 
     ) 
select contract_id 
     ,details1 
     ,details2 
     ,delete_date 
    from contracts_delta s 
    on duplicate key 
    update contracts.details1 = s.details1 
      ,contracts.details2 = s.details2 
      ,contracts.delete_date = s.delete_date; 

После «upsert», данные контракты будут выглядеть следующим образом:

mysql> select * from contracts; 
+-------------+----------+----------+-------------+ 
| contract_id | details1 | details2 | delete_date | 
+-------------+----------+----------+-------------+ 
|   1 | a1  | a2  | NULL  | 
|   2 | b1  | b2  | 2011-01-03 | 
|   3 | c1  | c2  | NULL  | 
|   4 | d1  | d2  | NULL  | 
+-------------+----------+----------+-------------+ 

- На данный момент вы можете удалить таблицу дельта (помните, чтобы воссоздать его в следующем время)

drop table contracts_delta; 

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

truncate table contracts_delta; 

- Или вы можете сохранить фактическую дельту (переименовать таблицу) упаковывает вам нужны отдельные дельты иногда

alter table contracts_delta rename to contracts_delta_20110115; 
+0

спасибо, Ronnis. Я в основном хочу знать, как бороться с дельта-случаем: 1) для строк обновления, mysql кажется не столь точным в отношении того, изменяется ли точная величина или нет. Даже вы обновляете строку с одинаковыми значениями, номер затронутой строки по-прежнему равен 1/2; 2) для удаленных строк, конечно, я не буду удалять строки навсегда. Однако я не уверен, что лучше удалить их в таблицу архивов или просто удалить удаленный флаг в одной таблице. – WilliamLou

+0

@ Ronnis: Я ищу особенно решение для удаления записей. В одном проекте мы используем флаг delete. Но что, если у вас есть уникальное ограничение для столбца, и вы хотите создать новую запись, которая нарушает уникальное ограничение. Определенно было бы лучше удалять данные в этом случае. Но как клиенты получают уведомление об удалении? Я мог представить себе создание второй таблицы для хранения идентификаторов и удаления даты удаленных записей. Решение без дополнительной таблицы было бы лучше. Какие-либо предложения? – Konsumierer

 Смежные вопросы

  • Нет связанных вопросов^_^