Page 1 of 1

solved: Deadlock with unknown reason

Posted: 02.12.2023, 10:29
by sglodek
Hello,

i use this code to save form-position and size on closing the form in "onClose-Event of the form.
If used on two working places it sometimes chrashes with an deadlock.
For example:
  • open a form in one session
  • open the same form in the second session
  • close the first form -> size an position saved
  • close the second form -> deadlock
This occures not always. Between the execSQL in the two session is a pause of one or two seconds so the execSQL will always be ready bofore the second execSQL starts.

I don't find the reason for the deadlock.

qryGeneric is a TZQuery with standard-settings. Nothing changed, only Conection-Proprty ist filled with the TZConnection.
I tried different transactionLevels in TZConnection, but the deadlock occures.

Can anyone give me a hint, what will be the reason for a deadlock, when there are some seconds between the execution of execSQL?

Code: Select all

Procedure SaveWindow(sName:String; x,y,w,h:Integer);
Begin
  with dmBISaM_SQL do
  begin
    qryGeneric.close;
    qryGeneric.SQL.Clear;
    qryGeneric.SQL.Add('select * from WINDOWS where name = ''' + sName +'''' );
    qryGeneric.open;
    if qryGeneric.RecordCount = 0 then
    begin
      qryGeneric.close;
      qryGeneric.sql.clear;
      qryGeneric.sql.add('INSERT INTO Windows (Name, XPos, YPos, Width, Height)');
      qryGeneric.sql.add('VALUES ('''+sName+''', '+IntToStr(x) +', ');
      qryGeneric.Sql.Add(IntToStr(y) +', '+IntToStr(w) +', '+IntToStr(h) +')');
      try
        qryGeneric.ExecSQL;
      except
      end;
    end
    else begin
      qryGeneric.close;
      qryGeneric.sql.clear;
      qryGeneric.sql.add('UPDATE Windows ');
      qryGeneric.sql.add('SET XPos='+IntToStr(x) + ', YPos=' + IntToStr(y) );
      qryGeneric.Sql.Add(', Width='+IntToStr(w) +', Height='+IntToStr(h));
      qryGeneric.sql.add(' WHERE name ='''+sName+'''');
      try
        qryGeneric.ExecSQL;
      except
      // sometimes this exception. 
        on e: exception do showMessage(e.message);
      end;
    end;
  end;
best regards
Siegbert

Re: Deadlock with unknown reason

Posted: 02.12.2023, 12:40
by sglodek
.. the error message may be helpful.
Is the deadlock only a second error and the original error is "Unsuccessful execution caused by an unavailable resource"?

SQL Error: deadlock; GDS Code: 335544336; deadlock; update conflicts with concurrent update; GDS Code: 335544451; Unsuccessful execution caused by an unavailable resource.; concurrent transaction number is 15775; GDS Code: 335544878; Unsuccessful execution caused by an unavailable resource.
Code: -913 SQL: UPDATE Windows SET XPos=267, YPos=61, Width=1093, Height=972 WHERE name ='Media'

Re: Deadlock with unknown reason

Posted: 03.12.2023, 13:31
by sglodek
Hello,

i changed again to transaction-Isolation tiReadCommitted and now ist works.
I don't know why it didn't work immediately :?

Siegbert
is it possible to mark a thread as solved?

Re: solved: Deadlock with unknown reason

Posted: 03.12.2023, 18:52
by aehimself
Hello,

I'm not sure how a failed execution can cause a deadlock. Are you sure it's a deadlock, or simply the OnClose event is interrupted by the exception and therefore your form never coses...?

I'd also reconsider the way how you are saving the data. If it takes only a second for your queries to execute the user might click more than once out of inpatience, resulting in AVs the second time it attempts to execute.
I'd make a background thread where you can push this information. Calling the workers method will simply store it in a TList so it returns instantly and when it has time it'll do the actual SQL operations.

The reason why transaction isolation can solve it if you are deadlocking yourself: Your query might be still locking the row you want to update with the select query. As transaction isolation changes the way how locking works (from no locking to table locking, you can read more in the RDBMSs manual) it might solve these issues for you.