AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Eigenartiger Effekt mit int-Primary Keys ?
Thema durchsuchen
Ansicht
Themen-Optionen

Eigenartiger Effekt mit int-Primary Keys ?

Ein Thema von gmc616 · begonnen am 3. Feb 2016 · letzter Beitrag vom 5. Feb 2016
Antwort Antwort
Seite 1 von 3  1 23      
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#1

Eigenartiger Effekt mit int-Primary Keys ?

  Alt 3. Feb 2016, 03:35
Datenbank: MSSQL Server • Version: xy • Zugriff über: TADO
Hallo Delphi-Gemeinde,

ich habe eine Anwendung geschrieben, welche mittler weile seit über 10 Jahren mehr oder weniger erfolgreich läuft. Eher mehr

Ich nutze zum Erstellen der Primärschlüssel eine eigene Funktion, welche aus einer Primärschlüssel-Tabelle einen Integer-Wert ermittelt, diesen um Eins hoch zählt ... usw.
Die AutoIdent-Funktion des MsSQL-Servers nutze ich nicht, da meine Anwendung teilweise auch auf anderen Datenbanken (z.B. dBase, Clipper ...) läuft, welche AutoIdent-Funktionen nicht kennen.

Zum Löschen von Datensätzen gibt es in meiner Anwendung eine Regel: Der Primärschlüssel wird negativ gesetzt und somit ist der Datensatz als gelöscht markiert. Kunden-Anforderung! (Aufgeräumt wird später).
Code:
UPDATE tabelle SET id=ABS(id)*-1 WHERE id=:ID;
TransactionLook ist aktiviert.

Mit dieser Regel läuft meine Anwendung seit Anfang an eigentlich recht stabil.

Mittlerweile ist meine Anwendung soweit fortgeschritten, dass es in einigen Kundeninstallationen einen Primärschlüssel im 5 Mio-Bereich verwendet. Und natürlich ist die Anwendung mittlerweile so groß, dass es sehr schwer ist, SQL-Fehler zu identifizieren. Voll allem dann, wenn es sich um einen Folgefehler handelt.

Das Problem: Der SQL-Befehl:
Code:
UPDATE tabelle SET id=ABS(id)*-1 WHERE id=:ID;
, wobei ID mit "5366038" belegt ist, schlägt fehl, da ein doppelter Primärschlüssel nicht zugelassen ist.
Das heißt, es soll eine Datensatz gelöscht markiert werden, welcher bereits gelöscht markiert ist. Und tatsächlich existiert zwei Datensätze, jeweils mit einem positiven ID und einem "gleichen" negativen ID. Das das nicht klappt ist klar.

Interessanter Weise tritt dieser Fehler NUR im MSSQL-2008R2 und MSSQL-2012 auf und immer bei den gleichen Schlüsseln 5366038 bzw. 5365874.
Ich habe ca. 20 Installationen am laufen, die diesen Fehler produziert haben. Und es betrifft immer einen dieser beiden Schlüssel.

Ich habe das ganze Programm durchwühlt und nach einer Ursache im Code gesucht, konnte aber nichts finden.
Aber Tatsache, dass dieser Fehler immer bei den gleichen IDs auftritt, bringt mir zu der Überzeugung, dass der Fehler nicht in meinem Programm-Code zu suchen ist, sondern wo anders.

Von Visual Studio 20xy MFC-Klassen kenne ich das Phänomen, dass dort ein Integer-Wert festgelegt wurde, welcher quasi als NULL definiert ist. Das war ein Bug von M$, welcher irgendwie gefixt wurde.
So soll (wenn ich das richtig verstanden haben) der (z.B.) SQL-Befehl:
Code:
UPDATE tabelle SET id=ABS(id)*-1 WHERE id=5365874;
vom MSSQL-Server als
Code:
UPDATE tabelle SET id=ABS(id)*-1 WHERE id =NULL;
übersetzt/interpretiert worden sein.

Kann es sein, dass in den Delphi-ADO-Klassen ein ähnliches Phänomen existiert?

Meine IDE: Delphi-2009 auf MS-Server 2008-R2.
Die Parameter (:ID) werden mit SetParam gesetzt, nicht direkt im SQL-Statement.
Die Verbindung zum SQL-Server wird über einen eigenen ConnectionString per SQLOLEDB aufgebaut.

Habt ihr ähnliche Erfahrungen?
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 3. Feb 2016, 07:26
Hallo,
dass es "versteckte" Integer-Werte gibt, habe ich noch nie gehört.
Quelle ?

Dein Problem solltest du doch an Deinem Rechner nachstellen können?

Ich denke eher, dass du Ids doppelt vergeben hast.
Genau dafür ist ja das Identity zumindestens beim MS-SQL da.
Andere DBs haben halt andere Mittel, um eindeutige Werte zu erzeugen.

Zumindestens sollte jedes DB einen Unique Index anbieten,
wobei das bei Dir nicht geholfen hätte (wegen dem negativ machen).


Heiko
Heiko

Geändert von hoika ( 3. Feb 2016 um 14:00 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#3

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 3. Feb 2016, 07:43
Vorschläge habe ich nicht, nur drei Fragen:
1. Wie markierst/löschst Du Fremdschlüssel?
2. Wieso setzt Du die ID auf einen negativen Wert, anstatt einfach ein 'Deleted'-Flag zu pflegen?
3. Welchen transaction Isolation level verwendest Du?
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#4

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 3. Feb 2016, 09:52
Nach der Beschreibung im Eröffnungsposting kann ich mir die Sache nicht anders erklären: Irgendwann wird ein PK negativ zu setzen versucht, wobei eine Kopie des Records mit dem positiven PK entsteht.

Vielleicht kann der DB-Server gar nicht anders handeln, wenn z.B. FKs in anderen Tabellen existieren, die auf diesen "positiven" PK deiner problematischen Tabelle verweisen, so daß dieser gar nicht gelöscht werden kann? Könntest du eventuell mal nachprüfen, ob irgendwelche FKs anderer Tabellen diese beiden problematischen Records über ihre PKs referenzieren?

Zusätzlich würde ich einmal versuchen, einen neuen Datensatz mit diesem problematischen PK anzulegen und danach zu löschen, und zwar debuggenderweise. Damit solltest du eigentlich punktgenau auf die Stelle stoßen, die den Fehler auslöst.

Beobachten oder gar nachvollziehen konnte ich dieses Verhalten bislang jedoch nicht (MsSQL, Firebird, MySQL). Wenn ich mal viel Zeit und Muse habe, probier ich's vielleicht mal aus ...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 3. Feb 2016, 10:15
Zitat:
Zumindestens sollte jedes DB einen Unique Index anbieten,
wobei das bei Dir nicht geholfen hätte (wegen dem negativ machen).
Er kann sich ja einen eigenen CHECK CONSTRAINT oder einen UNIQUE INDEX mit ABS() auf seine Indexspalten legen,
dann würde das Problem gleich beim zweiten ANLEGEN und nicht erst beim LÖSCHEN auffallen.

Zitat:
Ich nutze zum Erstellen der Primärschlüssel eine eigene Funktion, welche aus einer Primärschlüssel-Tabelle einen Integer-Wert ermittelt, diesen um Eins hoch zählt ... usw.
usw?
$2B or not $2B

Geändert von himitsu ( 3. Feb 2016 um 10:25 Uhr)
  Mit Zitat antworten Zitat
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 5. Feb 2016, 04:01
Hallo,
dass es "versteckte" Integer-Werte gibt, habe ich noch nie gehört.
Quelle ?
Auch wenns keine Quelle ist, aber ein Beispiel: http://stackoverflow.com/questions/1...field-exchange

Das dieser Effekt/Bug tatsächlich existiert haben ich live gesehen!
Geschrieben ist das Ganze im VS2010 in der afxdb.h

Vorschläge habe ich nicht, nur drei Fragen:
1. Wie markierst/löschst Du Fremdschlüssel?
Was verstehst du unter Fremdschlüssel? Hier gibt es nur Primary Keys und die gehören alle "mir".

2. Wieso setzt Du die ID auf einen negativen Wert, anstatt einfach ein 'Deleted'-Flag zu pflegen?
Klar, hätte man auch machen können. Ich habe mich damals für das Negativ-setzen entschieden. Für das aktuelle Problem wäre ein deleted-Flag evtl. die bessere Lösung gewesen.
Aber die 5 Mio Datensätze davor machen auch keine Probleme. Und in diesen 5 Mio Datensätzen sind ca. 20% mit negativem ID. Ja, gelöscht wird viel! Ein Großteil davon durchaus berechtigt.
3. Welchen transaction Isolation level verwendest Du?
Gute Frage! Was passiert denn, wenn man TAdoConnection.BeginTrans ruft?

Zitat:
Ich nutze zum Erstellen der Primärschlüssel eine eigene Funktion, welche aus einer Primärschlüssel-Tabelle einen Integer-Wert ermittelt, diesen um Eins hoch zählt ... usw.
usw?
Code:
// PseudoCode
TAdoCon.BeginTrans;

UPDATE nidents SET id=id+1 WHERE tbname=:TableName AND idname=:PkName;
SELECT id from nidents where tbname=:TableName AND idname=:PkName;

TAdoCon.CommitTrans;
Ein Unique Index über tbbame,idname existiert
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 5. Feb 2016, 05:39
Hallo,
nun das Bsp. beschreibt aber, dass der Nutzer die falsche Dummy-Variable benutzt hat.
Murks ist das trotzdem ...

Ich wollte doch aber wissen, ob du das nachstellen kannst.


Heiko
Heiko
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#8

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 5. Feb 2016, 06:53
Wie markierst/löschst Du Fremdschlüssel?
Was verstehst du unter Fremdschlüssel? Hier gibt es nur Primary Keys und die gehören alle "mir".
Was ein Primary Key (PK, Primärschlüssel) ist, weißt du ja bereits: eine eindeutige ID pro Datensatz in derselben Tabelle. Ein Fremdschlüssel (Foreign Key, FK) ist ein Key, der meistens auf einen PK einer anderen Tabelle verweist. Wenn du z.B. eine Tabelle ARTIKEL hast, die neben PK, Preis, Artikelnummer usw. auch eine Spalte enthält, in der eine Kategorie vermerkt werden soll, wäre es ja unsinnig, jedesmal den Kategorien-Namen dort reinzuschreiben. Stattdessen erzeugt man einen Tabelle KATEGORIEN, spendiert dieser einen PK und trägt dort die verfügbaren Kategorien ein. In der Artikeltabelle wird dann in der Spalte KATEGORIE nur noch der PK der Kategorientabelle gespeichert. Das ist dann ein Fremdschlüssel, auch wenn er dir gehört.

Ja, gelöscht wird viel! Ein Großteil davon durchaus berechtigt.
Wird auch unberechtigt gelöscht? Wie darf man das verstehen?

Grundsätzlich halte ich auch weiterhin für problematisch, wenn man ohne ausreichende Grundkenntnisse versucht, funktionierende Anwendungen für ein produktives Umfeld schreiben zu wollen.

Geändert von Perlsau ( 5. Feb 2016 um 06:59 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#9

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 5. Feb 2016, 07:32
Das dieser Effekt/Bug tatsächlich existiert haben ich live gesehen!
Geschrieben ist das Ganze im VS2010 in der afxdb.h
Der Bezug zu ADO fehlt mir hier und deine Interpretation im Eingangspost ist eindeutig falsch. Du verwechselst RFX mit SQL-Server. Und selbst wenn -aus welchen Gründen auch immer- ein 'UPDATE tabelle SET id=ABS(id)*-1 WHERE id =NULL;' ausgeführt werden würde, würde rein gar nichts passieren. Daran (also am Schlangenöl) kann es also nicht liegen.

Zitat:
Vorschläge habe ich nicht, nur drei Fragen:
1. Wie markierst/löschst Du Fremdschlüssel?
Was verstehst du unter Fremdschlüssel? Hier gibt es nur Primary Keys und die gehören alle "mir".
Du scheinst nur rudimentäres Grundwissen über Datenbanken zu haben. Daher auch dein Glaube an Schlangenöl.
Zitat:
3. Welchen transaction Isolation level verwendest Du?
Gute Frage! Was passiert denn, wenn man TAdoConnection.BeginTrans ruft?
Auch hier erkennt man dein fehlendes Wissen.
Um diese Frage zu beantworten, verwende den Profiler, oder schau Dir die Eigenschaften der Connection an. Wenn Du weißt, wie der Isolationlevel ist, dann weißt Du auch, wie sich der Server beim konkurrierenden Lesen verhält.

Natürlich ist das ärgerlich und irgendwo ist der Wurm. Aber ich lege meine Hand ins Feuer, das der SQL-Server mit NULL-Werten richtig umgehen kann.

Zeig doch mal die Definition der Tabelle mit den doppelten Ids. Wichtig ist auch die Definition vom Index sowie die Definition der 'idents-Tabelle'.
Beim SSMS gibt es die Funktion 'Generate Script'. Dort musst Du dann die eine Tabelle auswählen und in den Eigenschaften (ein Button auf der 3. Seite) noch einstellen, das auch der Index geskriptet werden soll. Das stellst Du dann hier ein und dann schauen wir weiter.

Du kannst versuchen, dein Updatestatement sicher zu machen, indem Du die 'OUTPUT' Klausel verwendest (obwohl Du damit nicht mehr kompatibel zu dBase bist).
Code:
UPDATE nidents
   SET id=id+1 
OUTPUT id
 WHERE tbname=:TableName
   AND idname=:PkName;
Damit hast Du eine atomare Anweisung, die garantiert transaktionssicher ist. Allerdings sind Probleme aufgrund der Nebenläufigkeit i.a. zufälliger Natur, d.h. Du müsstest eher zufällige doppelte Schlüssel beobachten.

Auch wenn es zum Haareraufen ist: Meist sitzt der Fehler 80cm vom Bildschirm entfernt.

Nebenbei: Wer will heutzutage noch kompatibel zu dbase sein, wo es doch freie Datenbanken gibt?

Geändert von Dejan Vu ( 5. Feb 2016 um 07:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Eigenartiger Effekt mit int-Primary Keys ?

  Alt 5. Feb 2016, 08:25
Zunächst einmal, alle Schlüssel dienen der internen Verwaltung von Daten. Wer von extern darauf zugreift und diese manipuliert gehört geteert und gefedert.
Was deinen Fehler angeht, wenn der/die Schlüssel bereits existieren, dann arbeitet Dein Schlüsselgenerator eben nicht zuverlässig, da das nicht auftreten darf.

Was heißt überhaupt negativ setzen? id:=id*-1 oder id:=id or $F000000 ?
Und wieviele Bits haben Deine Integers eigentlich? Wenn auch DBase versorgt werden muß, konnte das eigentlich schon mit 32Bit-Werten umgehen?

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:37 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz