5

Sto scrivendo un software di sincronizzazione che prenderà tutte le modifiche in un DB e le sincronizzerà su un altro DB. A tal fine ho aggiunto nella mia tabella di T due colonne:C'è una possibile condizione di competizione in questa istruzione UPDATE?

alter table T add LastUpdate rowversion, LastSync binary(8) not null default 0 

Ora posso facilmente selezionare tutte le righe che sono state modificate dall'ultima sincronizzazione:

select * from T where LastUpdate > LastSync 

Tuttavia dopo aver eseguito la sincronizzazione dovrei rendere i due campi uguali. Ma l'aggiornamento della riga aggiorna anche il timestamp, quindi devo fare questo:

update T set [email protected]@DBTS+1 where [email protected] 

Ma mi chiedo - Sarà questo lavoro sempre? Cosa succede se leggo il valore di @@DBTS e poi un altro utente riesce a inserire/aggiornare una riga da qualche parte prima che la mia riga venga confermata? È questo codice rischioso? E se sì, come potrebbe essere migliorato?

+0

A proposito, qual è la versione e l'edizione di SQL Server? [Change Data Capture] (http://msdn.microsoft.com/en-us/library/bb522489.aspx) è un'opzione? –

+0

@ Martin Smith - 2008, penso. Non sono sicuro di ciò che il cliente ha. –

+0

@ Martin Smith: ho controllato l'acquisizione dei dati di modifica, ma sarebbe stato eccessivo. Un semplice timestamp sarà sufficiente. Ho solo bisogno di sapere quali documenti devono ancora essere sincronizzati. Non ho bisogno della storia completa. –

risposta

-1

Se si esegue questa operazione in una transazione Serializable, nessun'altra lettura/scrittura sarà in grado di influire su queste tabelle.

RepeateableRead può anche fare il lavoro ...

+1

Tabelle - sì. Ma per quanto riguarda il valore di '@@ DBTS'? Questo non è memorizzato in nessuna tabella! –

+0

@Vilx Se si prende un blocco di tabella esclusivo per la durata della sincronizzazione, presumibilmente non importa se '@@ DBTS' viene incrementato da un evento in un'altra tabella. –

+0

@Martin Smith - ma @@ DBTS è globale per l'intero DB. Perché non importa? Se ottengo uno (più vecchio) valore per il campo 'LastSync' e uno più recente per il campo' LastUpdate', la mia sincronizzazione sarà interrotta. –

4

Memorizzazione "LastSync" nella stessa tabella come i dati reali non è forse una buona idea a tutti. Provare a memorizzarlo in un'altra tabella che non ha una rowversion. In questo modo si evita il problema di "aggiornamento della riga aggiorna il timestamp".

Il software Synchronizer può quindi lavorare in questo modo:

  • Prendi il valore @LastSync dalla tabella aggiuntiva
  • "Seleziona @ThisSync = max (LastUpdate) da T dove LastUpdate> @LastSync"
  • "Seleziona * da T dove LastUpdate> @LastSync e LastUpdate < = @ThisSync" sono le tue righe per la sincronizzazione
  • Memorizza @ThisSync come nuovo "LastSync" nella tabella aggiuntiva.

Le voci che vengono modificate mentre la sincronizzazione è in esecuzione avranno un valore di rowversion più alto rispetto alla query max(). Saranno sincronizzati la prossima volta che viene chiamato il tuo sincronizzatore.

+0

Questa è un'idea. Lo terrò a mente, nel caso non succeda nulla di meglio. –

Problemi correlati