2011-01-13 8 views
2

Es ist eine Frage zur Diskussion. Jetzt muss ich eine MySQL-Datenbanktabelle neu entwerfen. Im Grunde enthält diese Tabelle alle Vertragsdatensätze, die ich aus einer anderen Datenbank synchronisiert habe. Der Vertragssatz kann geändert oder gelöscht werden, oder Benutzer können neue Vertragssätze über die GUI-Schnittstelle hinzufügen. Zu diesem Zeitpunkt entspricht die Tabellenstruktur genau der Vertragsinfo (Spalte: Seriennummer, Ablaufdatum usw.). In diesem Fall kann ich nur die gesamte Tabelle synchronisieren (alle alten Datensätze löschen, durch neue ersetzen). Wenn ich die Tabelle synchronisieren möchte (nur mit modifizierten, neuen, gelöschten Datensätzen synchronisieren), wie sollte ich das Datenbankschema ändern?Datenbankschema für Delta-Synchronisation geeignet

hier ist die Methode, die ich kommen, aber ich brauche Ihre Vorschläge, weil ich denke, es ist ein häufiges Szenario in Datenbankanwendungen. 1) Einführung einer Sequenznummer Konzept/Spalte: Markieren Sie für jede Sequenz die neuen hinzugefügten Datensätze, modifizierte Datensätze, gelöschte Datensätze mit dieser Sequenznummer. Durch das Aufzeichnen der letzten synchronisierten Sequenznummer nur die Datensätze mit der höheren Sequenznummer übergeben;

2) Da gelöschte Verträge wieder hinzugefügt werden können, und die ursprüngliche Tabelle hat primäre Schlüsseleinschränkungen, sollte ich eine andere Tabelle für diese gelöschten Datensätze erstellen? oder fügen Sie eine Flag-Spalte hinzu, um anzugeben, ob dieser Vertrag gelöscht wurde?

Ich hoffe, ich erkläre meine Frage klar. Wie auch immer, wenn Sie irgendwelche Artikel oder Ihre eigenen Vorschläge dazu wissen, lassen Sie es mich bitte wissen. Vielen Dank!

Antwort

8

Ich denke, Sie sind mit dem Konzept eines Deltas verwechselt.

Entweder Sie erhalten volle Lasten (der gesamte Datensatz) oder nur die Änderungen (das "Delta").

Wenn Sie mit vollen Lasten arbeiten, können Sie einen trunkate + einfügen. Auf diese Weise müssen Sie nicht mit neuen oder alten Zeilen oder Löschungen umgehen. Dies kann nicht möglich sein, weil die referenziellen Integrität usw.

Wenn Sie ein Delta erhalten, wird jede Zeile der Regel in 1 von 2 Gruppen unterteilt:

  1. Matching key = UPDATE. Sie können festlegen, dass Zeilen mit identischen Daten ignoriert oder überschrieben werden.
  2. keine passenden Schlüssel = INSERT

Deletes ist etwas Besonderes. Zeilen, die nicht existieren, können nicht an Sie gesendet werden. Daher müssen Sie sich darauf einigen, wie Sie damit umgehen sollen. Bei voller Auslastung können Sie alle lokalen Zeilen löschen, die im empfangenen Datensatz nicht vorhanden sind.

Im Fall von Delta können Sie zustimmen, die Zeile mit einem Löschmarker (Flag, Datum) zu senden. Sie können dann entscheiden, ob Sie die Zeile mit einem Löschmarker (automatisch von (1) oben behandelt) beibehalten möchten, oder ob Sie Ihre Zeile DELETE sollten. Ich schlage vor, es zu behalten, denn früher oder später wird Ihnen jemand fehlende Zeilen/schlechte Datenqualität vorwerfen und dann werfen Sie das DELETE_DATE in ihr Gesicht.

Für MySQL können Sie verwenden, um "upsert" -Funktionalität zu implementieren.

Sie müssten mehr Details angeben, wenn Sie spezifischere Hilfe benötigen.

Update:

Ok, hier ist ein Beispiel.Sagen Sie, dass Sie die folgende Tabellenstruktur haben:

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

Jedes Mal, wenn Sie die aktualisierten Zeilen erhalten, können Sie sie in eine temporäre Tabelle mit identischer Struktur einfügen:

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

Einige Beispieldaten:

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 
+-------------+----------+----------+-------------+ 

Mit der Syntax, mit der ich früher verbunden habe, können Sie alle neuen Zeilen einfügen. Immer wenn die Zeile bereits vorhanden ist (doppelt vorhanden), haben wir uns dafür entschieden, die Spalten zu aktualisieren. Beachten Sie, dass gelöschte Zeilen automatisch behandelt werden, da delete_date eine reguläre Spalte wie alles andere ist.

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; 

Nach dem „Upsert“ werden die Daten in den Verträgen werden wie folgt aussehen:

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  | 
+-------------+----------+----------+-------------+ 

- An dieser Stelle können Sie wählen die Delta-Tabelle löschen (nicht vergessen, es neben neu zu erstellen Zeit)

drop table contracts_delta; 

- Oder man kann es nur gestutzt, um Platz zu sparen. (Sie müssen sicherstellen, dass es auf der nächsten Ladung sowieso leer ist)

truncate table contracts_delta; 

- Oder können Sie das aktuelle Delta speichern (benennen Sie die Tabelle) einhüllen Sie die einzelne Deltas müssen irgendwann

alter table contracts_delta rename to contracts_delta_20110115; 
+0

Dank, Ronnis. Ich möchte hauptsächlich wissen, wie man mit delta case umgeht: 1) Für Update-Zeilen scheint mysql nicht so genau zu sein, ob sich der genaue Wert ändert oder nicht. Selbst wenn Sie die Zeile mit denselben Werten aktualisieren, ist die betroffene Zeilennummer immer noch 1/2; 2) für gelöschte Zeilen werde ich natürlich die Zeilen nicht dauerhaft löschen. Ich bin mir jedoch nicht sicher, ob es besser ist, sie in eine Archivtabelle zu kopieren oder ein gelöschtes Flag in dieselbe Tabelle zu setzen. – WilliamLou

+0

@Ronnis: Ich suche vor allem nach einer Lösung zum Löschen von Datensätzen. In einem Projekt verwenden wir eine Löschflagge. Was aber, wenn Sie eine eindeutige Einschränkung für eine Spalte haben und einen neuen Datensatz erstellen möchten, der gegen die eindeutige Einschränkung verstößt? Es wäre definitiv besser, die Daten in diesem Fall vollständig zu löschen. Aber wie werden die Kunden über die Löschung informiert? Ich könnte mir vorstellen, eine zweite Tabelle zu erstellen, um die IDs zu speichern und das Datum der gelöschten Datensätze zu löschen. Eine Lösung ohne zusätzliche Tabelle wäre schöner. Irgendwelche Vorschläge? – Konsumierer