1

私の質問は非常に単純ですが、答えは難しいかもしれません。

私はPHPを使用しており、オブジェクトの一意のIDを手動で管理したいと考えています。トリッキーなのは、アトミック性を管理することです。2つの要素が同じIDを取得することは望ましくありません。

「要素」は「グループ」にグループ化されます。各グループで、要素IDを1から開始し、そのグループの挿入ごとに段階的に増やしていきます。

私の最初の解決策は、テーブル「Groups」に「lastID」列を含めることです。

CREATE TABLE groups ( id INT AUTO_INCREMENT, lastId INT )
CREATE TABLE elements ( myId INT, multiple values ...)

同じIDを持つ多くの要素を回避するには、lastIdを更新して、アトミックSQLクエリで選択する必要があります。

その後、1つ取得すると、再度選択できない一意のIDがあり、要素を挿入できます。

私の質問は、大胆な部分をどのように解決するかです。私のデータベースはMyISAMエンジンを搭載したMySQLであるため、トランザクションはサポートされていません。

UPDATE groups 
SET lastId = lastId + 1 
WHERE id = 42

SELECT lastId 
FROM groups
WHERE id = 42

これらの2つのリクエストよりもアトミックなものはありますか?

ありがとう

4

3 に答える 3

4
UPDATE groups SET lastId = last_insert_id(lastId + 1)

そして、あなたはあなたの新しいIDを取得することができます

SELECT last_insert_id()

パラメータとともに使用last_insert_idすると、値が保存され、後で呼び出すときに返されます。
自動番号を生成するこの方法は、行数が少ないMyISAMテーブルで最適に機能します(MyISAMは常にテーブル全体をロックします)。また、トランザクションの期間中はテーブルをロックしないという利点もあります(これは、InnoDBテーブルの場合に発生します)。

これはMySQLのマニュアルからです:

exprがLAST_INSERT_ID()の引数として指定されている場合、引数の値は関数によって返され、LAST_INSERT_ID()によって返される次の値として記憶されます。これは、シーケンスをシミュレートするために使用できます。

シーケンスカウンターを保持するテーブルを作成し、初期化します。

CREATE TABLE sequence (id INT NOT NULL); 
INSERT INTO sequence VALUES (0); 

この表を使用して、次のようなシーケンス番号を生成します。

UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID(); 

UPDATEステートメントはシーケンスカウンターをインクリメントし、LAST_INSERT_ID()への次の呼び出しで更新された値を返します。SELECTステートメントはその値を取得します。mysql_insert_id()CAPI関数を使用して値を取得することもできます。21.8.3.37項「mysql_insert_id()」を参照してください。

LAST_INSERT_ID()を呼び出さなくてもシーケンスを生成できますが、このように関数を使用することの有用性は、ID値が最後に自動的に生成された値としてサーバーに保持されることです。複数のクライアントがUPDATEステートメントを発行し、SELECTステートメント(またはmysql_insert_id())を使用して、独自のシーケンス値を生成する他のクライアントに影響を与えたり影響を受けたりすることなく、独自のシーケンス値を取得できるため、マルチユーザーにとって安全です。

于 2012-07-24T21:03:05.750 に答える
3

1つのオプションは、グループごとにauto_increment値をインクリメントできる気の利いたMyISAM機能を使用することです。

CREATE UNIQUE INDEX elements_ix1 ON要素(groupId、myID)

myID INT NOT NULL AUTO_INCREMENT

これは、別のテーブルの更新を伴うものよりも「アトミック」です。これはMyISAMでのみ機能し、InnoDBでは機能しないことに注意してください。


http://dev.mysql.com/doc/refman/5.1/en/example-auto-increment.htmlからの抜粋

MyISAMノート

MyISAMテーブルの場合、複数列インデックスの2次列にAUTO_INCREMENTを指定できます。この場合、AUTO_INCREMENT列の生成値は、MAX(auto_increment_column)+ 1 WHERE prefix=given-prefixとして計算されます。これは、データを順序付けられたグループに入れたい場合に役立ちます。

于 2012-07-24T21:09:13.447 に答える
0

MySQLのインストールには、トランザクションをサポートするInnoDBエンジンも含まれていると思います。テーブルのエンジンタイプを変更するだけです。

于 2012-07-24T21:03:07.627 に答える