Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi [Firebird] Alte Daten aus Tabelle löschen->deadlock (https://www.delphipraxis.net/136194-%5Bfirebird%5D-alte-daten-aus-tabelle-loeschen-deadlock.html)

alzaimar 25. Jun 2009 10:59

Datenbank: Firebird • Version: 2.1 • Zugriff über: Egal

[Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Hallo,

Habe folgende kleine Tabellen:
SQL-Code:
CREATE TABLE COUNTER (BUFFERSIZE INTEGER);

CREATE GENERATOR GEN_XMLBUFFER_ID;

CREATE TABLE XMLBUFFER (
    ID       INTEGER NOT NULL,
    TIMEDATE TIMESTAMP,
    DATA     BLOB SUB_TYPE 1 SEGMENT SIZE 80
);

ALTER TABLE XMLBUFFER ADD CONSTRAINT PK_XMLBUFFER PRIMARY KEY (ID);
CREATE INDEX XMLBUFFER_TIME ON XMLBUFFER (TIMEDATE);

SET TERM ^ ;

CREATE OR ALTER TRIGGER XMLBUFFER_BD0 FOR XMLBUFFER
ACTIVE BEFORE DELETE POSITION 0
AS
begin
   Update Counter set BufferSize = BufferSize - 1;
end
^
CREATE OR ALTER TRIGGER XMLBUFFER_BI FOR XMLBUFFER
ACTIVE BEFORE INSERT POSITION 0
as
begin
   Update Counter set BufferSize = BufferSize + 1;
  if (new.id is null) then
    new.id = gen_id(gen_xmlbuffer_id,1);
end
^
SET TERM ; ^
'COUNTER' enthält die Anzahl der Datensätze in der Tabelle 'XMLBUFFER'.

So, nun will ich die Tabelle 'XMLBUFFER' verkleinern. Dazu schnippel ich die ältesten 500 Records weg:
SQL-Code:
delete from xmlbuffer
  where id in (
    select first 500 id from xmlbuffer
    )
Leider klappt das nie, denn ich bekomme jedesmal den Fehler:
Zitat:

Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
lock conflict on no wait transaction.
deadlock.
update conflicts with concurrent update.
concurrent transaction number is 1799580.
At trigger 'XMLBUFFER_BD0' line: 5, col: 4.
Kann man das vermeiden, ohne die Trigger zu löschen, oder muss man damit leben?

TBx 25. Jun 2009 11:24

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Moin,

als erstes Mal löscht diese Anweisung alle Datensätze der Tabelle:

SQL-Code:
delete from xmlbuffer
  where id in (
    select first 500 id from xmlbuffer
    )
Das passiert deshalb, weil für jeden Datensatz separat nachgeguckt wird, ob er sich in den ersten 500 befindet. Dies ist immer der Fall, da der zuvor gelöschte Datensatz ja in der neuen Ergebnismenge nicht mehr vorkommt.

Deinen Deadlock erhälst Du also vermutlich, weil Du einer anderen Transaktion da Datensätze unter dem Allerwertesten klaust.

Vermeiden kannst Du das, indem Du den 500. Datensatz ermittelst und dann alle DS <= diesem löschst.

Das hat also nichts mit Deinen Triggern zu tun.

Aber dazu mal die Frage: Warum diese Verrenkung? Ist ein COUNT zu langsam?
Auf diese Weise die Anzahl der Datensätze vorzuhalten ist zumindest ungewöhnlich.

Gruß

Thomas

alzaimar 25. Jun 2009 12:22

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Hi

Ja, das COUNT ist zu langsam. Hier gibt es einen Thread darüber. Ich vermute, es liegt an den Blobs, denn FB rennt ja durch alle Records durch und mit anderen Tabellen geht das sehr schnell.

Und, NEIN, ich habe keine andere Transaktion offen. Ich vermute ja, das das zweite 'Update Counter' mit dem allerersten 'Update Counter' kollidiert.

Übrigens geht es so (danke für den Tipp)
SQL-Code:
delete from xmlbuffer
  where id < (
    select first 1 skip 500 id from xmlbuffer
    )

DeddyH 25. Jun 2009 12:31

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Mir hat mal jemand den Tipp gegeben, BLOBs in eine eigene Tabelle zu verlagern und eine 1:1-Beziehung einzurichten. Evtl. hilft das ja, so dass eine COUNT-Abfrage genügend schnell ist und Du auf Dein Konstrukt verzichten könntest.

alzaimar 26. Jun 2009 05:05

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Hi Detlef,

Gute Idee.

mkinzler 26. Jun 2009 05:27

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Wobei das in diesem Fall keinen große Änderung bringen könnte, da die Tabelle ja nur 3 Felder hat und die Blobs kein Teil des Tabellenspaces sein sollten.

alzaimar 26. Jun 2009 05:40

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Na ja. Ein Count(*) über eine Tabelle nur mit numerischen Werten geht sehr schnell, wohingegen das Count(*) über diese BLOB-Tabelle eine halbe Ewigkeit braucht.

Lemmy 26. Jun 2009 06:15

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Hi,

http://www.firebirdfaq.org/faq5/

Hast Du einen Index bei der Tabelle definiert? Wenn ja, geht ein "Select Count(ID)" schneller? Wobei du das auch so mal testen kannst...

Grüße
Lemmy

alzaimar 26. Jun 2009 06:24

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Diese Frage wurde -wie schon erwähnt- bereits diskutiert.
Mir ging es hier nur darum, die ersten 500 Datensätze zu löschen, ohne das mich FB zutextet. Mit der Idee von TBx geht es ja.

alex517 26. Jun 2009 07:22

Re: [Firebird] Alte Daten aus Tabelle löschen->deadlock
 
Zitat:

Zitat von alzaimar
Mir ging es hier nur darum, die ersten 500 Datensätze zu löschen, ohne das mich FB zutextet.

da du ja FB 2.1 verwendest, solltest du mal einem Blick auf
"ROWS" werfen. "ROWS" kann man nicht nur bei SELECT sondern auch
bei UPDATE und DELETE verwenden.

SQL-Code:
delete from xmlbuffer
order by ID
rows 500;
alex


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:17 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz