Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   MySQL Duplicate Entry Auto-Inc (https://www.delphipraxis.net/187741-mysql-duplicate-entry-auto-inc.html)

JRichmann 29. Dez 2015 14:58

Datenbank: MySQL • Version: 5.5.X • Zugriff über: UniDac

MySQL Duplicate Entry Auto-Inc
 
Hallo zusammen,

ich habe eine MySQL Tabelle mit einem Auto-Inc Primary Key.

CREATE TABLE `AAA` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
...
...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=39378 DEFAULT CHARSET=utf8
;


Es gibt nur einen einzigen localen Client auf der DB. Dieser graift mittels UniDac auf die DB zu.

Dieser Client empfängt Daten via Internet von diversen Sendern (mobile Geräte).
Für jeden Empfänger wird ein Thread aufgebaut. Jeder Thread schreibt seine Daten in
obige Tabelle. Es kommen 0-20 Sätze je Sekunde an.

Das klappt auch soweit... ABER gelegentlich erhalte ich einen Primary Key Error (Duplicate Entry).
MySQL hat dann tataäschlich den gleichen PKey 2 mal vergeben.
Es scheint mir, als on MySQL mit den Therads nicht klar kommt bzw. mit der Masse der Sendungen.
Aber 0-20 Sätze je Sekunden sind ja nun nicht wirklich viel.

Leider weiß ich mir überhaupt keinen Rat mehr.
In meinem Code kann ich einfach keinen BUG sehen oder finden.

Hat jemand eine Idee ?

Grüße

borncrush 29. Dez 2015 15:05

AW: MySQL Duplicate Entry Auto-Inc
 
Kannst Du zeigen, wie Du die DB befüllst (SQL-Statement)?

JRichmann 29. Dez 2015 15:19

AW: MySQL Duplicate Entry Auto-Inc
 
Ja... aber es ist aufgrund der Struktur der Klassen und Threads sicher nicht so sehr einfach lesbar bzw. verständlich.

Delphi-Quellcode:
function TSQLObjectRTTI.ComposeInsert(cl: TClass; idFieldName: String;
  forceId: Boolean): String;
var
  sep: String;
  fieldInfo: TFieldInfo;
  rttiType: TRttiType;
  props: TArray<TRttiProperty>;
  prop: TRttiProperty;
  fields, values: String;
begin
  rttiType := GetTypeInfo(cl);

  fields := '';
  values := '';

  props := rttiType.GetProperties;
  for prop in props do
  begin
    if prop.Visibility = TMemberVisibility.mvPublished then
      if not IsBlob(prop.PropertyType) then
      begin
        if fields <> '' then sep := ' , ';
        if SameText(idFieldName, prop.Name) then
        begin
          if forceId then
          begin
            fields := fields + sep + '`' + prop.Name + '`';
            values := values + sep + ':' + prop.Name;
          end;
        end
        else
        begin
          fields := fields + sep + '`' + prop.Name + '`';
          values := values + sep + ':' + prop.Name;
        end;
      end;
  end;


  Result := Format('INSERT INTO %s (%s) VALUES (%s)',
                    [
                      ClassToTableName(cl),
                      fields,
                      values
                    ]);
end;

nahpets 29. Dez 2015 16:31

AW: MySQL Duplicate Entry Auto-Inc
 
Ist die 'id' in dem Statement enthalten?
Delphi-Quellcode:
Result := Format('INSERT INTO %s (%s) VALUES (%s)',[ClassToTableName(cl),fields,values]);
Wenn ja, stelle sicher, dass dem nicht so ist.

Weiß nicht, wie sich MySQL verhält, wenn man für ein Auto-Increment-Feld einen Wert liefert. Nimmt es auf jeden Fall einen eigenen neuen Wert oder übernimmt MySQL dann den "gelieferten" Wert?

Wenn ich Deinen Quelltext richtig verstehe, sollte forceId auf jeden Fall false sein oder für die ID explizit Null geliefert werden.

So in der Art:
Delphi-Quellcode:
if forceId then begin
  fields := fields + sep + '`' + prop.Name + '`';
  values := values + sep + 'Null';
end;

JRichmann 29. Dez 2015 16:36

AW: MySQL Duplicate Entry Auto-Inc
 
Hallo...

das Auto-INC Feld ist NICHT enthalten... es taucht im SQL String nicht auf.
(wenn es enthalten ist und auch gefüllt, dann kommt MySQL nicht klar).

nahpets 29. Dez 2015 16:50

AW: MySQL Duplicate Entry Auto-Inc
 
Wenn also sichergestellt ist, dass die ID nicht vomn Client geliefert wird, kann es nur ein datenbankseitiges Problem sein, eine Fehlersuche in Deinen Quellen dürfte sich damit erübrigen.

Schau mal bitte, ob Du hier weitere Infos findest: https://www.benefind.de/web.php?q=my...icate+Entry%22
Es scheint jedenfalls häufiger ein ähnliches "Problem" zu geben.

JRichmann 29. Dez 2015 18:55

AW: MySQL Duplicate Entry Auto-Inc
 
> kann es nur ein datenbankseitiges Problem sein, eine Fehlersuche in Deinen Quellen dürfte sich damit erübrigen

Ja..... (leider sehe ich das auch so).

Ich denke, schon, dass der Fehler im Code liegt.... Aber nicht so einfach.
Im Kern streikt wohl MySQL (es muss aber irgendwie an der Benutzung von MySQL liegen.... und dann doch wieder am Code)

jobo 29. Dez 2015 19:09

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von JRichmann (Beitrag 1325518)
Hallo...

das Auto-INC Feld ist NICHT enthalten... es taucht im SQL String nicht auf.
(wenn es enthalten ist und auch gefüllt, dann kommt MySQL nicht klar).

Ich sehe jetzt an dem Code nicht, dass das ID Feld ausgeschlossen wird. Im Gegenteil, die "Props" werden dynamisch abgefragt und daraus das Statement gebaut.
Vielleicht doch mit ID, ab und zu?
Oder hast Du die konkreten SQL Statements vorliegen, wenn der Fehler zuschlägt?

Sir Rufo 29. Dez 2015 20:22

AW: MySQL Duplicate Entry Auto-Inc
 
Hat denn jeder Thread auch seine eigene Connection?

Wenn nicht, dann ist das auch kein Wunder mit der doppelten ID Vergabe.

jobo 30. Dez 2015 06:50

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von Sir Rufo (Beitrag 1325549)
Hat denn jeder Thread auch seine eigene Connection?

Wenn nicht, dann ist das auch kein Wunder mit der doppelten ID Vergabe.

Wenn die ID nicht mitgeschickt wird, sondern wirklich von der DB generiert wird, sollte das doch wohl piepegal sein, oder?

ot
ich würde sofort die DB wechseln, wenn es auch nur nach solchen Problemen riecht. Bei diesem System auch aus anderen Gründen. Kann seit einigen Jahren nicht mehr nachvollziehen, warum so häufig oder überhaupt mysql eingesetzt wird.
/ot

Sir Rufo 30. Dez 2015 08:14

AW: MySQL Duplicate Entry Auto-Inc
 
@jobo

Wenn du mit mehr als einem Thread auf die gleiche Session zugreifst dann kann bei jeder DB alles passieren (meistens Grütze).

Jede Session ist an einen Thread gebunden und bei einer vernünftigen Implementierung (dieses Connection-Objekts) würde dir eine Exception um die Ohren fliegen, wenn du mit mehr als einem Thread gleichzeitig darauf zugreifst.

TRomano 30. Dez 2015 08:20

AW: MySQL Duplicate Entry Auto-Inc
 
Damit hast Du vollkommen Recht Sir Rufo (jeder Thread eine Connection), aber Jobo meinte, dass, wenn die ID vom DBMS erzeugt wird, eigentlich nichts passieren sollte.
Das DBMS bekommt über das INSERT-Statement eine Anforderung für eine neue ID (auto increment) und sollte diese auch entsprechend bereit stellen. Was clientseitig passiert ist da erst einmal egal (Threads) ... ist schon komisch, dass das DBMS das irgenwie nicht hinbekommt.

Sir Rufo 30. Dez 2015 08:28

AW: MySQL Duplicate Entry Auto-Inc
 
Es werden auch 2 IDs erzeugt, aber die letzte wurde bei beiden Datensätzen eingetragen (per
SQL-Code:
last_inserted_id
) :stupid:

Die beiden Statements müssen nur zeitlich sehr dumm zusammenfallen. Man spricht hier von einer Bei Google suchenrace condition

jobo 30. Dez 2015 08:38

AW: MySQL Duplicate Entry Auto-Inc
 
Also ich habe sowas noch nie gehabt. Wenn sowas tatsächlich passiert, müsste ich über einen Kirchenaustritt nachdenken. ;)
Ich arbeite allerdings auch nicht produktiv mit mysql.
Bevor ich dem nachgehen würde (aus Neugier), würde ich lieber andere Dinge prüfen:
- Datentyp der Auto Inc Spalte, scheint hier groß genug
- Dictionary Schrott durch manuelle Einträge, scheints ja hier zu geben. Wurde zumindest testhalber durchgeführt. Also AutoInc Wert per Alter Table neu setzen ("heilen")
- Sicherstellen(!), dass die Grundannahme "nur ein Client" tatsächlich richtig ist.

TRomano 30. Dez 2015 08:45

AW: MySQL Duplicate Entry Auto-Inc
 
@Sir Rufo: Okay. Wenn man nur eine Connection für mehrere Threads (mit INSERT-Statements) benutzt kann die MySQL-Server-Variable LAST_INSERTED_ID nicht unbedint dem entsprechen, was man sich so vorstellt ... das hatte ich nicht beachtet.
Ich gehe einfach davon aus, dass MySQL die ID´s richtig erzeugt (AutoInc), sonst hätten wir schon Gegenteiliges gehört :-D

@jobo: du musst bestimmt nicht deswegen aus der Kirche austreten, hier läuft bestimmt was Anderes schief ... :?

borncrush 30. Dez 2015 09:01

AW: MySQL Duplicate Entry Auto-Inc
 
Mich wundert das auch arg.

Wir befeuern einige MySQL Server mit vielen, gar massig an Datensätzen. Teilweise Standortdaten zur Routenberechnnung in Logistikzentren. Da kommen teilweise viele Datensätze in einer Sekunde an. Wir konnten aber noch nie diesen Effekt beobachten mit MySQL+MSSQL (hier nicht gefragt) beobachten. Mehr Datenbankverwaltungssysteme kenne ich nicht produktiv.

Du schließt die Übergabe der ID (des PK / AI-Feldes) aus. Somit ist also MySQL gefragt. --> ok
Sicherlich habt ihr die my.ini konfiguriert. Könnte Dir da ein Zusammenhang einfallen? (Clustern werdet ihr ja nicht, oder?? Da fehlt mir die Erfahrung)
Andernfalls interessiert mich noch die Storage-Engine. --> InnoDB?

jobo 30. Dez 2015 09:28

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von TRomano (Beitrag 1325580)
@jobo: du musst bestimmt nicht deswegen aus der Kirche austreten, hier läuft bestimmt was Anderes schief ... :?

Wenn ich es mir genau überlege, ist es hier wie überall die Frage, kämpfe ich innerhalb des Systems um Verbesserungen oder such ich mir was besseres.
Bei mysql war ich zum Glück noch nie gezwungen, es produktiv zu verwenden.

JRichmann 30. Dez 2015 10:11

AW: MySQL Duplicate Entry Auto-Inc
 
Hallo...

>Hat denn jeder Thread auch seine eigene Connection?

Ja

Die DB kann ich leider nicht so einfach wechseln

JRichmann 30. Dez 2015 10:15

AW: MySQL Duplicate Entry Auto-Inc
 
>Du schließt die Übergabe der ID (des PK / AI-Feldes) aus. Somit ist also MySQL gefragt. --> ok

Ja

>Sicherlich habt ihr die my.ini konfiguriert. Könnte Dir da ein Zusammenhang einfallen? (Clustern werdet ihr ja nicht, oder?? Da fehlt mir die Erfahrung)

Default Werte

>Andernfalls interessiert mich noch die Storage-Engine. --> InnoDB?

InnoDB

TRomano 30. Dez 2015 10:20

AW: MySQL Duplicate Entry Auto-Inc
 
@Jobo: ich bin auch nicht wirklich ein großer Freund von mySQL (alleine ein Wechsel auf Version 5.7 von 5.6.xx brachte einen Haufen Ärger), aber des Kunden Wunsch sei mir Befehl !
Für die dortige einfache DB hätte ich weiterhin Firebird genommen (alleine schon weger der Lizenz-Problematik). Aber man wollte dort bei der Hansestadt die IT-Landschaft vereinheitlichen. Ich habe mich durchgekämpft und es läuft sehr stabil. Es sind aber auch keine riesigen Datenmengen, so dass ich zur Stabilität dahingehend nichts sagen kann und will.

Sir Rufo 30. Dez 2015 10:23

AW: MySQL Duplicate Entry Auto-Inc
 
Dann trifft dich eventuell dieser Bug
https://bugs.mysql.com/bug.php?id=67526

jobo 30. Dez 2015 10:34

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von JRichmann (Beitrag 1325598)
Die DB kann ich leider nicht so einfach wechseln

So ist es ja häufig, solche Art "Lösungen" schlage ich idR auch nicht vor. Was ist mit Datentypen und Reset des des Auto Inc Wertes oder mglw. vorhandenen "Testdaten" aus irgendwelchen Versuchen?
Hast Du mal max Wert von Auto Inc mit dem Bestand abgeglichen?

@TRomano: Eine Vereinheitlichung des Systemlandschaft finde ich eine gute Sache. Aber warum bloß in diese Richtung? Als Liebhaber von Verschörungstheorien aller Art, würde ich dahinter etwas Lobbyarbeit vermuten. Der nächste Schritt dort ist dann wahrscheinlich, ganz auf Oracle DB umzustellen.
Wir haben bei einem Projekt für ein großes Softwareunternehmen nur ein paar Jahre gebraucht, sie von mysql abzubringen. Dabei waren es nicht mal die Admins, die dort nur die Entwicklungssysteme betreuen, die viel Bedenkzeit brauchten. Es ging vermutlich um den Betrieb im Rechenzentrum eines Schwesterunternehmens, soweit ich das beurteilen kann.

jobo 30. Dez 2015 10:55

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von Sir Rufo (Beitrag 1325603)
Dann trifft dich eventuell dieser Bug
https://bugs.mysql.com/bug.php?id=67526

Oder der darin verwiesene:
http://bugs.mysql.com/bug.php?id=76872

Da wäre es wohl ratsam, mal zu versuchen, den Effekt einzugrenzen.

TRomano 30. Dez 2015 10:56

AW: MySQL Duplicate Entry Auto-Inc
 
@Jobo: ich weiß nicht, wie man Sie davon abbringen kann. Kein Geld im Stadtsäckel, aber so einen Unsinn machen. Eigentlich brauchten sie nur einen neue Client-Software und ein paar Aufräumarbeiten in der Firebird-DB (über 400 SP´s für einzelne UPDATE-Statements) und ein wenig Umstruktuierung, aber Gottes (also die Hansestadt) Wege sind unergründlich !!!
Und ich glaube auch nicht, dass sie wirklich wissen, was sie tun. Mit der Lizenz-Politik von Oracle bin ich nicht zu 100% vertraut, aber trauen tue ich larry schon lange nicht mehr.
Meine Empfehlung wäre auch eine andere gewesen, aber wenn OpenSource-DB dann bitte richtig. Ich weiß natürlich nicht, was mittlerweile alles dort auf mySQL läuft, aber man sollte sich da richtig (vorher) beraten oder beraten lassen, was man tut.

jobo 30. Dez 2015 13:17

AW: MySQL Duplicate Entry Auto-Inc
 
Die Lizenzbestimmungen für mysql kenne ich auch nicht.
Aber mysql ist ne gute Rutsche für Clustersysteme- davon gibt's ja nicht viele- und generell einfach Supportverträge.

Bernhard Geyer 30. Dez 2015 13:40

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von jobo (Beitrag 1325607)
Zitat:

Zitat von Sir Rufo (Beitrag 1325603)
Dann trifft dich eventuell dieser Bug
https://bugs.mysql.com/bug.php?id=67526

Oder der darin verwiesene:
http://bugs.mysql.com/bug.php?id=76872

Da wäre es wohl ratsam, mal zu versuchen, den Effekt einzugrenzen.

Einzugrenzen indem z.B. einfach mal eine neuere Minor-Version installiert wird.
Bei MySQL schleichen sich teilweise haarsträubenden Fehler in Bugfix-Versionen ein.
Es gab mal eine (zufälligerweise nach erscheinen Intern geprüft) bei der wurden alle varchar-Felder als Blob-Felder gemeldet :wall:.

Bernhard Geyer 30. Dez 2015 13:42

AW: MySQL Duplicate Entry Auto-Inc
 
Zitat:

Zitat von jobo (Beitrag 1325625)
Die Lizenzbestimmungen für mysql kenne ich auch nicht.

Blos kein ODBC oder libmysql.dll verwenden. Schwubs bist du in der GPL-Falle (nach Oracle-Redensart) und darfst jede Installation von MySQL lizenzieren wenn du keine Quelloffene SW entwickelst.
Glücklicherweise gibts Komponenten von Devart die das nicht nötig haben bzw. ja auch Maria-DB um dort sich (bei Java/JDBC-Anwendungen) bedienen zu können.

JRichmann 31. Dez 2015 08:54

AW: MySQL Duplicate Entry Auto-Inc
 
>Hat denn jeder Thread auch seine eigene Connection?
JA

>Vielleicht doch mit ID, ab und zu?
Nein... definitiv nein

>Ich würde sofort die DB wechseln, wenn es auch nur nach solchen Problemen riecht.
geht leider nicht

JRichmann 31. Dez 2015 09:09

AW: MySQL Duplicate Entry Auto-Inc
 
Ich habe MySQL schon oft verwendet.... Bisher hatte ich auch noch nie ein solches Problem.
Es werden hier zwar nun 1 bis 20 Sätze je Sekunde geschrieben (i.d.R. aber nur 3-4-5 je Sekunde).
Eigentlich müsste die DB das dock packen. Oder etwa nicht ?

Und es läuft auch 2-3-4 Stunden alles glatt und dann schlägt der Fehler zu.
Wenn der Fehler einmal aufgetreten ist.... dann kommt er ab diesem Zeitpunkt öfter.
Alle paar Minuten.

Sir Rufo 31. Dez 2015 09:38

AW: MySQL Duplicate Entry Auto-Inc
 
Du brauchst den Server nicht zu wechseln, sondern nur eine Einstellung am Server vornehmen (so wie in dem Link beschrieben)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:55 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