2

重複の可能性:
PostgreSQL で挿入が失敗した場合に nextval() の呼び出しを回避する方法はありますか?
Rails - Postgres は削除された ID を再利用しませんが、MySql は再利用しますか?

PostgreSQL 9.2.1を使用した非常に単純なデータベースがあります。このメソッドを使用してDoctrine2で何かを挿入すると:

$em->persist($entity);
$em->flush();

エラーが発生した場合

-レコードが挿入されていないことを意味します-

1それはまだ私の主キーに追加されます。したがって、ページ50時間を更新すると、自動インクリメント値が に設定されていると表示され50ます。どうすればこれを防ぐことができますか? 主キーが増える理由よりもレコードが挿入されていない場合。これは非常に重要です。これはインデックスを何の目的もなく使用し、数が増え続けるためです。

私はそれが何から来たのかわからないので、何も試しませんでした. この時点で非常に行き詰まっています。

4

2 に答える 2

5

Doctrine2 はトランザクションを使用してタスクを完了します。

Doctrine がその変更をデータベースにフラッシュするたびに、トランザクションが開かれ、各レコードが準備され、コミットが一度にすべての変更を処理します。

このプロセス中に、auto_incrementID を必要とするレコードが割り当てられます。その後、コミット フェーズでレコードが失敗した場合、レコードは追加されませんが、自動インクリメントによってその ID が発行されます。

ここでトランザクションの詳細を読むことができます: http://www.postgresql.org/docs/current/static/tutorial-transactions.html

注: これは MySQL でも同じで、他の多くの RDBMS でも同じだと思います。

于 2012-10-21T00:36:14.817 に答える
2

実質的なパフォーマンスの低下や不適切な同時操作を発生させずに、観察した動作を回避する方法はありません。

自動インクリメント フィールドは、を介してフィールドをシーケンスに結び付けることによって実装されdefault nextval('seqeunce_name')ます。

シーケンスは、同時操作でも常に一意の値を発行することを保証するように設計されています。常に連続した値を発行するという保証はありません。行を挿入しようとしてがnextval()呼び出されると、値が発行され、 を使用してシーケンスを手動でリセットしない限り、シーケンスによって再度発行されることはありませんsetval()

シーケンスを安全にインクリメントすると必然的にロック オーバーヘッドが発生するため、高度な同時操作では、過度のロックを回避するために、一部の dbms システムがトランザクションまたはセッションごとにシーケンス値のセットをキャッシュします。これにより、スキップされたシーケンス値の問題がさらに悪化します。postgres では、このような値のキャッシングはCACHE cache、シーケンス作成の句によって制御されます。

于 2012-10-21T01:05:30.627 に答える