Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (Deutsch) » MobiLink - Clientadministration » SQL Anywhere-Clients für MobiLink » Skriptgesteuerter Upload

 

Überlegungen zur Planung von skriptgesteuerten Uploads

Ein Vorgang pro Zeile

Der Upload darf nicht mehr als einen Vorgang (Einfügen, Aktualisieren oder Löschen) pro Einzelzeile enthalten. Sie können jedoch mehrere Vorgänge in einem einzigen Upload kombinieren. Wenn beispielsweise eine Zeile eingefügt und dann aktualisiert wird, können Sie diese beiden Vorgänge in einem Vorgang kombinieren, indem Sie einmalig die endgültigen Werte einfügen.

Reihenfolge der Vorgänge

Wenn der Upload in die konsolidierte Datenbank aufgenommen wird, werden Einfügungen und Aktualisierungen vor Löschungen vorgenommen. Sie können diese Reihenfolge der Vorgänge in einer gegebenen Tabelle nicht ändern.

Konfliktbehandlung

Ein Konflikt tritt auf, wenn eine Zeile zwischen Synchronisationen in mehr als einer Datenbank aktualisiert wird. Der MobiLink-Server kann Konflikte erkennen, da jede Aktualisierung in einem Upload das Pre-Image der Zeile enthält, die aktualisiert werden soll. Das Pre-Image ist der Wert jeder Spalte in der Zeile zum Zeitpunkt des letzten erfolgreichen Uploads oder Downloads. Der MobiLink-Server meldet einen Konflikt, wenn das Pre-Image nicht mit den Werten in der konsolidierten Datenbank übereinstimmt.

Wenn Sie in Ihrer Anwendung die Konflikterkennung implementieren müssen und Sie skriptgesteuerte Uploads verwenden, müssen Sie in der entfernten Datenbank den Wert jeder Zeile zum Zeitpunkt des letzten erfolgreichen Uploads oder Downloads überprüfen. Auf diese Weise können Sie die korrekten Pre-Images heraufladen.

Eine Möglichkeit, die Daten von Pre-Images zu pflegen, besteht darin, eine Pre-Image-Tabelle zu erstellen, die mit der Synchronisationstabelle identisch ist. Sie können dann in Ihrer Synchronisationstabelle einen Trigger erstellen, der die Pre-Image-Tabelle bei jeder Aktualisierung neu mit Daten füllt. Nach einem erfolgreichen Upload können Sie die Zeilen in der Pre-Image-Tabelle löschen.

Ein Beispiel zu Lösung von Konflikten finden Sie unter Beispiel für einen skriptgesteuerten Upload.

Konflikte nicht behandeln

Wenn Sie Konflikte nicht behandeln müssen, können Sie die Anwendung deutlich vereinfachen, indem Sie Pre-Images nicht protokollieren. Stattdessen können Sie Aktualisierungen einfach in einem Einfügevorgang heraufladen. Schreiben Sie dazu ein upload_insert-Skript in der konsolidierten Datenbank, das eine Zeile einfügt, wenn diese noch nicht vorhanden ist, oder eine bereits existierende Zeile aktualisiert. Wenn Sie eine konsolidierte SQL Anywhere-Datenbank verwenden, erreichen Sie dies mit der ON EXISTING-Klausel in der INSERT-Anweisung Ihres upload_insert-Skripts.

Weitere Hinweise finden Sie unter INSERT-Anweisung.

Wenn Sie Konflikte nicht beheben und zwei oder mehr entfernte Datenbanken dieselbe Zeile ändern, überschreibt die zuletzt synchronisierte Zeile die früheren Änderungen.

Erzwungene Konflikte behandeln

Bei Löschungen ist es wichtig, dass der Primärschlüssel der Zeile, die aktualisiert wird, korrekt ist. In den meisten Fällen ist es allerdings unbedeutend, ob die Werte von nicht als Primärschlüssel definierten Spalten mit denen in der konsolidierten Datenbank übereinstimmen. Die Werte von nicht als Primärschlüssel definierten Spalten sind nur wichtig, wenn der MobiLink-Server den erzwungenen Konfliktmodus verwendet. In diesem Fall werden alle Spaltenwerte an das Skript upload_old_row_insert in der konsolidierten Datenbank übergeben. Abhängig davon, wie Sie dieses Skript implementiert haben, müssen die Werte von nicht als Primärschlüssel definierten Spalten korrekt sein.

Weitere Hinweise finden Sie unter Erzwungene Konflikte.

Sperren

Sie können viele der Probleme mit skriptgesteuerten Uploads vermeiden, indem Sie die Standardeinstellung für die erweiterte dbmlsync-Option LockTables verwenden. Dann erhält dbmlsync Exklusivsperren für alle Synchronisationstabellen, bevor der Upload aufgebaut wird. Dadurch wird verhindert, dass andere Verbindungen die Synchronisationstabellen ändern, während die Skripten den Upload aufbauen. Außerdem wird so sichergestellt, dass keine nicht festgeschriebenen Transaktionen in offenen Synchronisationstabellen vorhanden sind, wenn der Upload aufgebaut wird.

Weitere Hinweise zur Aufhebung der Tabellensperrung finden Sie unter Skriptgesteuerter Upload ohne Tabellensperre.

Redundante Uploads

In den meisten Fällen muss jeder Vorgang nur genau einmal in die entfernte Datenbank geladen werden. MobiLink unterstützt sie dabei, indem für jede Subskription ein Fortschrittswert verwaltet wird. Standardmäßig entspricht der Fortschrittswert dem Zeitpunkt, an dem dbmlsync mit dem letzten erfolgreichen Upload begonnen hat. Dieser Fortschrittswert kann mithilfe des Hooks sp_hook_dbmlsync_set_upload_end_progress mit einem anderen Wert überschrieben werden.

Weitere Hinweise finden Sie unter sp_hook_dbmlsync_set_upload_end_progress.

Jedes Mal, wenn eine der Upload-Prozeduren aufgerufen wird, werden Werte über die Tabelle #hook_dict an sie übergeben. Dazu gehören die Werte für den 'Start-Verarbeitungsfortschritt' und 'Abschluss-Verarbeitungsfortschritt'. Diese Werte definieren den Zeitraum, in dem der Upload, der gerade aufgebaut wird, Änderungen der entfernten Datenbank enthalten sollte. Vorgänge, die vor dem 'Start-Verarbeitungsfortschritt' aufgetreten sind, wurden bereits heraufgeladen. Änderungen, die nach dem 'Abschluss-Verarbeitungsfortschritt' aufgetreten sind, sollten während der nächsten Synchronisation heraufgeladen werden.

Unbekannter Upload-Status

Ein häufiger Fehler bei der Implementierung von skriptgesteuerten Uploads ist die Erstellung von gespeicherten Prozeduren, die nur über die Hooks sp_hook_dbmlsync_upload_end oder sp_hook_dbmlsync_end ermitteln können, ob ein Upload erfolgreich in die konsolidierte Datenbank übernommen wurde. Diese Methode ist unzuverlässig.

Im folgenden Beispiel werden Einfügungen über ein Bit auf jeder Zeile durchgeführt, um zu überprüfen, ob eine Zeile aktualisiert werden muss. Das Bit wird beim Einfügen einer Zeile eingestellt und nach einem erfolgreichen Upload durch den Hook sp_hook_dbmlsync_upload_end gelöscht.

//
// DO NOT DO THIS!
//
CREATE TABLE t1 (
   pk    integer primary key,
   val      varchar( 256 ),
   to_upload   bit DEFAULT 1
);

CREATE PROCEDURE t1_ins()
RESULT( pk integer, val varchar(256) )
BEGIN
    SELECT pk, val
    FROM t1
    WHERE to_upload = 1;
END; 

CREATE PROCEDURE sp_hook_dbmlsync_upload_end()
BEGIN
    DECLARE     upload_status   varchar(256);

    SELECT value
    INTO upload_status
    FROM #hook_dict
    WHERE name = 'upload status';

    if upload_status = 'committed' THEN
        UPDATE t1 SET to_upload = 0;
    END IF
END;

      CREATE PUBLICATION p1 WITH SCRIPTED UPLOAD (
           TABLE t1 USING ( PROCEDURE t1_ins FOR UPLOAD INSERT )
      );

Dieser Ansatz funktioniert meistens. Der Vorgang schlägt fehl, wenn ein Hardware- oder Softwarefehler auftritt, durch den dbmlsync gestoppt wird, nachdem der Upload gesendet wurde, aber bevor er vom Server bestätigt wurde. In diesem Fall wird der Upload zwar möglicherweise in die konsolidierte Datenbank übernommen, aber der Hook sp_hook_dbmlsync_upload_end wird nicht aufgerufen und die to_upload-Bits werden nicht gelöscht. Das bedeutet, dass bei der nächsten Synchronisation Einfügungen für Zeilen heraufgeladen werden, für die bereits ein Upload erfolgt ist. In diesem Fall schlägt die Synchronisation normalerweise fehl, da in der konsolidierten Datenbank ein Fehler wegen mehrfach vorhandener Primärschlüssel generiert wird.

Probleme können außerdem auftreten, wenn die Verbindung mit dem MobiLink-Server abbricht, nachdem der Upload gesendet wurde, aber bevor er bestätigt wurde. In diesem Fall kann dbmlsync nicht feststellen, ob der Upload erfolgreich übernommen wurde. Das Dienstprogramm dbmlsync ruft den Hook sp_hook_dbmlsync_upload_end auf und setzt den Upload-Status auf unbekannt. Dieser Hook verhindert das Löschen der to_upload-Bits. Das ist korrekt, wenn der Upload nicht vom Server übernommen wurde. Wurde der Upload jedoch übernommen, tritt das Problem auf, das bereits im vorherigen Absatz beschrieben wurde. In beiden Fällen ist die betroffene entfernte Datenbank nicht in der Lage, eine weitere Synchronisation durchzuführen, solange das Problem nicht manuell behoben wurde.

Datenverlust während des Downloads verhindern

Wenn Sie skriptgesteuerte Uploads verwenden, kann es vorkommen, dass Daten in der entfernten Datenbank, für die ein Upload erfolgen muss, durch Daten überschrieben werden, die aus der konsolidierten Datenbank heruntergeladen werden. Dies bewirkt, dass Änderungen verloren gehen, die in der entfernten Datenbank durchgeführt wurden. Dbmlsync verhindert diesen Datenverlust, wenn jeder Upload, der von Ihren Upload-Prozeduren aufgebaut wird, alle Änderungen enthält, die in der entfernten Datenbank festgeschrieben wurden, bevor der Hook sp_hook_dbmlsync_set_upload_end_progress aufgerufen wurde.

Im nachfolgenden Beispiel wird gezeigt, wie Daten verloren gehen können, wenn Sie diese Regel verletzen:

Zeit
1:05:00 Eine Zeile R, die sowohl in der konsolidierten Datenbank als auch in entfernten Datenbanken existiert, wird mit neuen Werten R1 in der entfernten Datenbank aktualisiert und die Änderung wird festgeschrieben.
1:06:00 Die Zeile R wird in der konsolidierten Datenbank mit neuen Werten R2 aktualisiert und die Änderung wird festgeschrieben.
1:07:00 Eine Synchronisation wird vorgenommen. Die Upload-Skripten sind so geschrieben, dass der Upload nur Vorgänge enthält, die vor 1:00:00 festgeschrieben wurden. Dies verletzt unsere Regel, da die Vorgänge, die vor dem Aufbau des Uploads durchgeführt wurden, vom Upload nicht erfasst werden. Die Änderung von Zeile R wird nicht einbezogen, da sie nach 1:00:00 durchgeführt wurde. Der vom Server erhaltene Download enthält die Zeile R2. Wenn der Download übernommen wird, ersetzt die Zeile R2 die Zeile R1 in der entfernten Datenbank. Die Aktualisierung in der entfernten Datenbank geht verloren.

Dbmlsync benutzt eine Reihe von Mechanismen, um sicherzustellen, dass der Download Änderungen nicht überschreibt, die nicht festgeschrieben waren, als der Hook sp_hook_dbmlsync_set_upload_end_progress aufgerufen wurde, oder festgeschrieben wurden, nachdem der Hook sp_hook_dbmlsync_set_upload_end_progress aufgerufen wurde.

Jede Änderung, die festgeschrieben wurde, bevor der Hook aufgerufen wurde, ist nicht geschützt und kann überschrieben werden, wenn der Download übernommen wird. Wenn hingegen die Änderung in den Upload aufgenommen wurde (der gesendet wurde, bevor der Download aufgebaut wurde), wird die Änderung an den MobiLink-Server geschickt und Ihre serverseitigen Skripten sind in der Lage, diese Situation mithilfe der Daten in der konsolidierten Datenbank aufzulösen, bevor der Download aufgebaut wird.


Skriptgesteuerter Upload ohne Tabellensperre