solved: Deadlock with unknown reason

The offical for ZeosLib 7.3 Report problems, ask for help, post proposals for the new version of Zeoslib 7.3/v8
Quick Info:
-We made two new drivers: odbc(raw and unicode version) and oledb
-GUID domain/field-defined support for FB
-extended error infos of Firebird
-performance ups are still in queue
In future some more feature will arrive, so stay tuned and don't hassitate to help
Post Reply
sglodek
Fresh Boarder
Fresh Boarder
Posts: 11
Joined: 13.02.2020, 20:08

solved: Deadlock with unknown reason

Post 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
Last edited by sglodek on 03.12.2023, 13:33, edited 1 time in total.
sglodek
Fresh Boarder
Fresh Boarder
Posts: 11
Joined: 13.02.2020, 20:08

Re: Deadlock with unknown reason

Post 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'
sglodek
Fresh Boarder
Fresh Boarder
Posts: 11
Joined: 13.02.2020, 20:08

Re: Deadlock with unknown reason

Post 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?
User avatar
aehimself
Zeos Dev Team
Zeos Dev Team
Posts: 765
Joined: 18.11.2018, 17:37
Location: Hungary

Re: solved: Deadlock with unknown reason

Post 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.
Delphi 12.1, Zeos 8 from latest GIT snapshot
Using:
- MySQL server 8.0.18; libmariadb.dll 3.3.8
- Oracle server 11.2.0, 12.1.0, 19.0.0; oci.dll 21.13
- MSSQL 2012, 2019; sybdb.dll FreeTDS_2435
- SQLite 3.45.2
Post Reply