Frage

ich auf einer Datenbankanwendung arbeite, die meist wird nur gelesen, aber es gibt eine Tabelle, die Benutzerbewegung in der App erfasst und verfügt über eine große Anzahl von Schreibvorgängen zu. Für alle paar tausend schreibt, sehen wir ein paar Ausnahmen im Fehlerprotokoll wie folgt:

[WARN][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] SQL Error: 1062, SQLState: 23000
[ERROR][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] Duplicate entry '17011' for key 1
[ERROR][2009-07-30 11:09:20,083][org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
  at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
  at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
  at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)

Die Tabelle in Frage hat das folgende Schema:

CREATE TABLE IF NOT EXISTS `my_table` (
  `id` int(11) NOT NULL,
  `data1` int(11) NOT NULL,
  `data2` int(11) NOT NULL,
  `timestamp` datetime default NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Und die entsprechende Hibernate Mapping XML:

<hibernate-mapping>
  <class name="mycorp.MyClass" table="my_table">
    <id name="id" column="id" type="java.lang.Integer">
      <generator class="increment"/>
    </id>
    <property name="data1" column="data1" type="java.lang.Integer"/>
    <property name="data2" column="data2" type="java.lang.Integer"/>
    <property name="timestamp" column="timestamp" type="java.util.Date"/>
  </class>
</hibernate-mapping>

Es ist möglich, wenn auch unwahrscheinlich, dass mehrere Instanzen unserer Webapp auf die Datenbank auf einmal schreiben könnten, da wir Versionsnummern in unserem Webapp Kontext nahtlos neue Versionen der Anwendungen freizugeben. Kunden mit der alten Version der Anwendung in ihrem Web-Browser im Cache gespeichert somit die alten Versionen des Servers zugreifen würde, die wir nach einigen Wochen deimplementieren.

Wie auch immer, ich bin nicht davon überzeugt, dass dies das Problem ist, aber ich bin misstrauisch, dass es einige Synchronisierungsprobleme zwischen MySQL und bei der Hand Hibernate hier. Würde meinen Generator Sequenz, seqhilo oder hilo Hilfe zu ändern? Auch, wenn Sie ein Beispiel für die Einrichtung eines solchen Generators in MySQL zur Verfügung stellen kann, das wäre sehr hilfreich sein, da die meisten der Online-Ressourcen sind einfach kleistert Kopie aus dem beklagenswert minimalistisch Beispiele in der Hibernate-Handbuch.

War es hilfreich?

Lösung

Increment ist definitiv schlecht, wenn man mehr als ein Prozess schriftlich an den gleichen Tisch hat - Sie sind verpflichtet, Kollisionen haben.

Da es sich um MySQL wir reden, die einfachste Sache wäre zu bedienen sein identity. In Ihrem Hibernate Mapping:

<generator class="identity"/>

In Ihrem MySQL-Skript:

CREATE TABLE IF NOT EXISTS `my_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `data1` int(11) NOT NULL,
  `data2` int(11) NOT NULL,
  `timestamp` datetime default NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Um eine bestehende Tabelle zu ändern:

ALTER TABLE `my_table`
  CHANGE COLUMN `id` `id` int(11) NOT NULL AUTO_INCREMENT=$NEW_VALUE$;

Dabei steht $ NEW_VALUE $ durch die nächste verfügbare ID ersetzt werden sollte, so dass Sequenz 1 nicht zurückgesetzt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top