2009-07-30 8 views
7

私はほとんどが読み取り専用ですが、アプリケーションのユーザーの動きを記録し、それに多くの書き込みを持っている1つのテーブルがあるデータベースアプリケーションに取り組んでいます。問題のテーブルには、次のスキーマを持っているHibernateから重複エントリエラーを取得すると、MySQLは責任を負いますか?

[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) 

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; 

と、対応するHibernateマッピング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> 

ウェブアプリケーションの複数のインスタンスがデータベースに同時に書き込む可能性があります。これは、Webアプリケーションコンテキストのバージョン番号が新しいvアプリケーションの数ウェブブラウザにキャッシュされた古いバージョンのアプリケーションを持つクライアントは、古いバージョンのサーバにアクセスし、数週間後にアンデプロイします。

とにかく、これは問題ではないと私は確信していますが、MySQLとHibernateの間に同期の問題があることは疑いがあります。私の発電機をシーケンス、seqhiloまたはhiloに変更するのが助けになるでしょうか?また、MySQLでそのようなジェネレータを設定する例を提供できるなら、それは非常に役に立ちます.Hibernateマニュアルの悲惨な最小限の例から、ほとんどのオンラインリソースを単純にコピーペーストします。

答えて

9

同じテーブルに複数のプロセス書き込みを行っている場合、インクリメントは間違いです。つまり、衝突する可能性があります。

私たちが話しているのはMySQLだから、もっとも簡単なものはidentityです。 MySQLのスクリプトで

<generator class="identity"/> 

:あなたのHibernateマッピングで

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; 

は、既存のテーブルを変更するには、次の

ALTER TABLE `my_table` 
    CHANGE COLUMN `id` `id` int(11) NOT NULL AUTO_INCREMENT=$NEW_VALUE$; 
$ NEW_VALUE $が利用可能な次のIDで置き換える必要があります

ので、そのシーケンスは1にリセットされません。

+0

非常に徹底した明確な答えです - ありがとう! –

関連する問題