Hi Michael
I only know roughly what is a deadlock. AFAIK it works as follows. When you update a row in a table, the dbms does the following:
1. put a lock on that row (to prevent simultaneous updates by different processes)
2. update the row
3. removes the lock.
When step 3 fails and another user/process tries to update that record you can get a deadlock.
However, in my case the deadlock appears when I am
inserting records in some table, in which case I think nothing is to be locked. So I don't fully apprehend the phenomenon.
In the past I had some like thing. I then used ZQuery->ExecSQL, and it disappeared when using ZConnection->ExecuteDirect. Possibly ZConnection->ExecuteDirect waits for reaction from the server, while ZQuery->ExecSQL does not? But now I'm using ZConnection->ExecuteDirect...
I cannot give a simple code example, for it happens not always at the same time. Likely dependent on database traffic.
So far as I can see in the stack the EZSQLException is raised in CheckMySQLError, but the exception reaches not the calling code of my C++ program.
Here is the code:
Code: Select all
procedure CheckMySQLError(PlainDriver: IZMySQLPlainDriver;
Handle: PZMySQLConnect; LogCategory: TZLoggingCategory; const LogMessage: string);
var
ErrorMessage: string;
ErrorCode: Integer;
begin
ErrorMessage := Trim(String(StrPas(PlainDriver.GetLastError(Handle))));
ErrorCode := PlainDriver.GetLastErrorCode(Handle);
if (ErrorCode <> 0) and (ErrorMessage <> '') then
begin
if SilentMySQLError > 0 then
raise EZMySQLSilentException.CreateFmt(SSQLError1, [ErrorMessage]);
DriverManager.LogError(LogCategory, PlainDriver.GetProtocol, LogMessage,
ErrorCode, ErrorMessage);
raise EZSQLException.CreateWithCode(ErrorCode,
Format(SSQLError1, [ErrorMessage]));
end;
end;
called from:
function TZMySQLStatement.ExecuteUpdate(const SQL: string): Integer;
var
QueryHandle: PZMySQLResult;
HasResultset : Boolean;
begin
Result := -1;
{$IFDEF DELPHI12_UP}
if FPlainDriver.ExecQuery(FHandle, PAnsiChar(AnsiString(SQL))) = 0 then
{$ELSE}
if FPlainDriver.ExecQuery(FHandle, PAnsiChar(SQL)) = 0 then
{$ENDIF}
begin
DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
HasResultSet := FPlainDriver.ResultSetExists(FHandle);
{ Process queries with result sets }
if HasResultSet then
begin
QueryHandle := FPlainDriver.StoreResult(FHandle);
if QueryHandle <> nil then
begin
Result := FPlainDriver.GetRowCount(QueryHandle);
FPlainDriver.FreeResult(QueryHandle);
end
else
Result := FPlainDriver.GetAffectedRows(FHandle);
end
{ Process regular query }
else
Result := FPlainDriver.GetAffectedRows(FHandle);
end
else
CheckMySQLError(FPlainDriver, FHandle, lcExecute, SQL);
LastUpdateCount := Result;
end;
called from:
function TZAbstractConnection.ExecuteDirect(SQL:string; var RowsAffected:integer):boolean;
var
stmt : IZStatement;
begin
try
try
CheckConnected;
stmt := DbcConnection.CreateStatement;
RowsAffected:= stmt.ExecuteUpdate(SQL);
result := (RowsAffected <> -1);
except
RowsAffected := -1;
result := False;
end;
finally
stmt:=nil;
end;
end;
called from:
function TZAbstractConnection.ExecuteDirect(SQL : String) : boolean;
var
dummy : Integer;
begin
result:= ExecuteDirect(SQL,dummy);
end;