La mia familiarità è con il mondo server Microsoft SQL che utilizza ADO (dbGo) e ho scritto molte applicazioni per quell'ambiente. Ora ho un'applicazione legacy Delphi 7 con un database Firebird 2.5 che devo mantenere.Come rendere l'applicazione client Firebird in attesa della riga da sbloccare
ma sto trovando è che se 2 applicazioni client esegue questo:
SQLQuery.SQL.Text := 'Update mytable set field1 = 11 where keyfield = 99'
SQLQuery.Execute;
a quasi esattamente nello stesso momento, il 2 ° applicazione ottiene immediatamente un errore di "stallo". In SQL Server, ci sarebbe stato un periodo di attesa
ADOConnection.Isolationlevel = ilCursorstability;
ADOConnection.CommandTimeout := 5;
prima di qualsiasi eccezione è sollevata nella seconda applicazione client. La gestione delle eccezioni potrebbe comportare un rollback in quella che sarebbe considerata una situazione molto insolita all'interno di un processo batch. Questo è ragionevole. 5 secondi è un tempo terribilmente lungo nei tempi di elaborazione del computer.
Ora i miei tentativi di utilizzare la stessa metodologia sul client Firebird sono stati infruttuosi perché il "deadlock" (in realtà, un record in uso) si verifica immediatamente.
Se il motore del database non può essere configurato per attendere un po 'per migliorare le condizioni (blocchi di registrazione da rilasciare), la responsabilità deve ora riposare con lo sviluppatore dell'applicazione client che deve scrivere codice follemente lento per superare ciò che sembra essere il principale fallimento di Firebird.
Una volta che è stata rilevata la "situazione di stallo", la condizione non chiara eccezione scollegando il componente di connessione
while rowsupdated = 0 and counter < 5 do
begin
try
rowsupdated := SQLQuery.Execute;
except
SQLConnection.Connected := False;
SQLConnection.Connected := True;
end;
Inc(Counter)
end;
Come si fa a fare robuste clienti tavolo-aggiornamento multi-utente, quando non si dispone di qualsiasi sostanziale tolleranza di blocco in Firebird, usando DBX in Delphi?
Non ho usato FirebirdSQL da un po ', ma ricordo che c'era una funzionalità SELECT FOR UPDATE WITH LOCK che poteva essere usata al livello SQL. Leggi questo: http://www.firebirdsql.org/refdocs/langrefupd25-notes-withlock.html – quasoft
Il valore predefinito per IsolationLevel per una connessione DBExpress a Interbase è 'ReadCommitted', che è l'equivalente di' ilCursorstability'. Il 'CommandTImeout' non esiste, ma c'è' WaitOnLocks', che ha come valore predefinito 'Vero' e significa * Specifica che una transazione attende l'accesso se incontra un conflitto di blocco con un'altra transazione * (secondo i documenti). Entrambi sono impostati nei parametri della connessione. –
Nonostante tutti i miei tentativi di configurare il client in modo diverso, sembra di default 'nowait'. Vedi la mia domanda a @TOndrej qui sotto. – nolaspeaker