SQlite - rowid kommt mehrfach vor

OP (Firma: JDCC) #4929673
Lesenswert?

Servus,

folgendes Problem:

Ich entwickle eine Archivsoftware unter SQLite + Web, das System ist
aktiv und läuft. Sporadisch (ca. 20 mal in den letzten 2 Jahren) tritt
ein merkwüdiges Problem auf: Ich habe mehrfach vergebene rowids, die
Daten nur des letzten Records sind in der db.

Programmausschnitt:

erstes db-Handle: offene Zieedatebank, attached ist eine weitere db
mit Daten. Die Dateen sollen von de zweiten in die erste transferiert
werden (es sind unterschiedliche db-files).

begin immediate
insert into archiv eetcpp.
return value == 0 -> alles ok, löschen in der ersten und end transaction
return value != 0 -> rollback; und Ende

Im Fehlerfall erscheint bei bis zu 5 aufeinandelfolgenden inserts die
gleiche rowid - darf ja eigentlich nicht seein. Alle returns von SQLite
sind 0 und versuchen mir zu sagen, alles sei ok.

Während der transaction aktualisiere ich noch eine andere Datenbank
über eine andere connection.

Gefunden habe ich das auf der Suche nach fehlenden Belegen. 
Protokolliert
ist der Vorgang auch (Ausschnitt):

----------------------

Barcode 60000000078034
  Ablagedatum (BELEG_DATUM = 15.05.2015) 15.05.2015, Ablagejahr 2015
  execute ARCHIV: 'attach 'E:\++++\AKTUELL\ruk\temp\archiv.sdb' as 
'tempdb''
    0.0000 sec, 1 Versuch(e)
    Standard-Barcode E:\++++\AKTUELL\ruk\temp\03379876.pdf
  Schreibe PDF        : E:\++++\AKTUELL\ruk\temp\03379876.pdf -> 
E:\ACCON\AKTUELL\ruk\2015\archiv_0515.t, 4960708 Bytes at $073afb4c
  execute ARCHIV: 'begin immediate'
    0.0000 sec, 1 Versuch(e)

  Aktualisiere History für '60000000078034', Jahr 2015
  execute HISTORY: 'update history set PRTFILE  = 
'usquery_impidx_20170303-08001014.prt, 
usquery_impwf_20170307-12001024.prt',
    LOCATION = 'ruk/2015', ARCDAT = '2017-03-07', STATUS = 'archiviert' 
where BARCODE_NR = '60000000078034''
    0.0000 sec, 1 Versuch(e)
  SQLAppend INSERT INTO ARCHIV
    (FPOS,BARCODE_NR,BELEG_DATUM,BELEG_KZ,BELEG_NR,BELEG_NUMMER,BEL_ART,BETR 
AG_1,BETRAG_2,BETRAG_3,BETRAG_4,BRUTTO,BUCHUNG_DATUM,KOMMENTAR,LOESCH_KZ 
,NETTO,REGULIERUNGS_KZ,SAP_BU_KREIS_R3,SAP_MA_NR_R3,SCANDATUM_R3,URSP_KZ 
,VL_NR,VORGANGS_ID,VORGANGS_NR,WAEHRUNG,WAWI_NR,REISENDER,WF_Import,SaKo 
nto,KOSTSTELL,SCANDATE,LOGFILE,IDXNR)
    VALUES
    ('0515 
73afb4c','60000000078034','2015-05-15','R','','69007827','00100032','000 
000000','000000000','000000000','000000000','226,86','2015-05-15','MS 
HAMBURG 
HAM1515','X','226,86','0','0008','60','','0000000000','2008','0000000000 
0000000000','00000000000000','EUR','00000','','03.03.2017','445030','',' 
','','03379876'),  result 0
  rowid 383721
  Lösche aus temp: delete from tempdb.archiv where BARCODE_NR = 
'60000000078034' = 0
  end transaction = 0
  detach temp = 0
  ok
  -> archiviert

---------------

Der Beleg ist dann weg. Der nächste hat die gleiche rowid ...

Vielleicht hat jemand eine Idee (im Web habe ich nur gefunden daß SQLite
das alles kann). Die Änderung in HISTORY sind vorhanden, die anderen 
nicht.
OP (Firma: JDCC) #4929793
Lesenswert?

Clemens L. schrieb:
> Das könnte ein Fehler in deinem Code sein ...

Schön wär's ;)

Ich habe das einige Male pingelig kontrolliert, ich befürchte Nein.
Im Moment bin ich schlicht ratlos.

Es passiert ja auch ziemlich selten ...

Nach dem Datenimport (jeweils ein PDF und Indexdaten) läuft ein
Prüfprogramm was zu jeder rowid prüft ob die Sachen da sind. Das
hat dann natürlich keinen Fehler gefunden. Vor ein Paar Wochen
habe ich die Prüfung af rowid und Barcode_Nr erweitert und bin
so auf den Effekt gekommen.
Gast #4930694
Lesenswert?

>ein merkwüdiges Problem auf: Ich habe mehrfach vergebene rowids

lass mich raten wie das Abläuft

1. gibts die rowid schon? -> nein -> Insert <- das ist der Fehler in 
deiner Erkennung
2. Update rowid-Satz auf neue Daten -> alter Satz wird auch 
überschrieben

https://www.techonthenet.com/sqlite/unique.php

sowas ohne Constraint zu machen ist wie Autofahren ohne Gurt - er ist da 
- es wird dadurch sicherer - vermeidet Unfälle - NUTZE DEN GURT

mit einem Unique Constraint kannst du die doppelte rowid gar nicht ohne 
das SQLite einen Fehler meldet mit Insert in deine Datenbank bekommen - 
dein händisches Prüfen ist definitiv falsch - es kann nicht anders 
passieren
Gast #4930955
Lesenswert?

>die rowid wird von SQLite vergeben. Ich habe da keinen Einfluß drauf.
>Nach dem insert hole ich mir die von SQLite per
>sqkite3_last_insert_rowid() ab.

hast du mehrere Threads welche die selbe connection nutzen - oder kann 
dein "Web" das verursachen?

würde aber nur dazu führen können das du z.B. eine falsche rowid 
bekommst

und laut: https://www.sqlite.org/autoinc.html

>In SQLite, table rows normally have a 64-bit signed integer ROWID which is 
>unique among all rows in the same table. (WITHOUT ROWID tables are the 
>exception.)

sollte es gar nicht möglich sein das du doppelte rowids im Table hast

ausser hier: https://www.sqlite.org/c3ref/last_insert_rowid.html

>If a separate thread performs a new INSERT on the same database connection >while 
the sqlite3_last_insert_rowid() function is running and thus changes >the last 
insert rowid, then the value returned by >sqlite3_last_insert_rowid() is 
unpredictable and might not equal either >the >old or the new last insert rowid.

und darüber der text bezüglich "funktioniert" und nicht funktioniert ist 
auch ein wenig schwierig

imer Internt habe ich noch diesen Tip gefunden

>  begin;
>    insert into tbl( filed ) VALUES ( 1 );
>    Select last_insert_rowid() as li;
>  commit;
#4930963
Lesenswert?

Joachim D. schrieb:
> Ich weiß nicht ob ich da Mist gebaut habe oder es ein Problem von
> SQLite ist.

Dass es ein Bug in SQLite ist, ist extrem unwahrscheinlich.

Dass du ein Dateisystem/OS/Hardware benutzt, das die Daten einfach 
wegschmeißt, hast du oben ausgeschlossen. Also bleiben nur Fehler im 
Zusammenhang mit Threading, oder irgendwelche anderen Programmierfehler.
OP (Firma: JDCC) #4930976
Lesenswert?

> Dass es ein Bug in SQLite ist, ist extrem unwahrscheinlich.

Äh ... klar. Ich glaube das ja auch nicht (und weiß es nicht).

> Dass du ein Dateisystem/OS/Hardware benutzt, das die Daten einfach
> wegschmeißt, hast du oben ausgeschlossen. Also bleiben nur Fehler im
> Zusammenhang mit Threading, oder irgendwelche anderen Programmierfehler.

Oder nicht so verwendet wie sich SQLite das gedacht hat. Das Problem
ist, ich kann es nicht bewußt herbeiführen - dazu passiert es zu selten.
Aktuell wurde knapp 400.000 Belege so bearbeitet, 2 mal hat es gezickt.

Ich könnte mir vorstellen, daß SQLite vielleicht ein Problem mit der
transaction und der in einer anderen connection geöffneten Datenbank
hat. Vielleicht bezieht sich die transaction nur genau auf die
aktuelle connnectioon (das Web sagt, es gehe).

Wenn ich da irgendwo Mist gebaut habe, kann ich das wenigstens abstellen 
;)
#4931071
Lesenswert?

Joachim D. schrieb:
> Ich könnte mir vorstellen, daß SQLite vielleicht ein Problem mit der
> transaction und der in einer anderen connection geöffneten Datenbank
> hat. Vielleicht bezieht sich die transaction nur genau auf die
> aktuelle connnectioon (das Web sagt, es gehe).

Zwischen Connections und Transaktionen ist eine 1:1-Beziehung. Mit 
Transaktionen kannst du verschieden Connections voneinander isolieren.

Aber ich habe keine Ahnung, ob dein Code Transaktionen korrekt benutzt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren