PHP で、MySQL を触っています


で、MySQL は、トランザクションが使えないということなのですが

例えば、

TALBE1 という名前のテーブルに
ID(int),VALUE(char)
という列があって
IDを、auto increment でない使い方をする場合

select max(ID) from TABLE1;

で取得した値を、newID として保存した後

insert into ID, VALUE values(newID, newVALUE);

で保管する以外に、方法はないもんでしょうか?

トランザクションがないので、重複したIDが投入されそうで気持ち悪くて・・・(まぁ、小規模では、可能性は殆どないと思うのですが)

#最新のバージョンでは、トランザクションが使えるようですが、とりあえず、そうでなかった場合に・・・

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2007/04/12 20:16:34
  • 終了:2007/04/16 16:53:25

ベストアンサー

id:kurukuru-neko No.3

kurukuru-neko回答回数1844ベストアンサー獲得回数1552007/04/13 01:38:20

ポイント22pt

単純に1レコードの追加であればエラー

IDをPRIMARY INDEXにして重複キーエラー

で処理した方軽いと思います。

(今回の処理もIDがユニークが前提)

追加する文字が'ADD VALUE'の場合

insert into TABLE1 (ID,VALUE)

select

if(ID is NULL,0,max(ID))+1 as ID,

'ADD VALUE' as VALUE

from TABLE1 for update

を実行した時重複した場合エラーになり

PHPのmysql_errnoでエラーが重複エラー(1062)

ならSQLを再実行する。

http://dev.mysql.com/doc/refman/4.1/en/error-messages-server.htm...

id:rikimaru

色々あって面白いですね

非常に、興味深いです

2007/04/13 10:42:55

その他の回答(3件)

id:studioes No.1

studioes回答回数523ベストアンサー獲得回数612007/04/12 20:46:07

ポイント23pt

テーブルロックすれば良いんじゃ・・・?

http://q.hatena.ne.jp/

id:rikimaru

http://dev.mysql.com/doc/refman/4.1/ja/internal-locking.html

これですね、なるほど、なるほど

2007/04/12 21:01:04
id:b-wind No.2

b-wind回答回数3344ベストアンサー獲得回数4402007/04/12 23:59:49

ポイント23pt

MySQL でトランザクションが使える InnoDB が採用されたのは 4.0 から。

さすがにそれ以前のバージョンは古すぎると思いますが、実際バージョンはいくらでしょうか?


自分なら、カウンター用に auto increment なカラムを持ったテーブルを別途用意します。

ダミーで INSERT を発行した後、LAST_INSERT_ID 関数を使えばユニークな値が取り出せます。

MySQL AB :: MySQL 4.1 リファレンスマニュアル :: 6.3.6.2 その他の各種関数

id:rikimaru

これも、いい解決策ですね

参考になりました

2007/04/13 00:16:06
id:kurukuru-neko No.3

kurukuru-neko回答回数1844ベストアンサー獲得回数1552007/04/13 01:38:20ここでベストアンサー

ポイント22pt

単純に1レコードの追加であればエラー

IDをPRIMARY INDEXにして重複キーエラー

で処理した方軽いと思います。

(今回の処理もIDがユニークが前提)

追加する文字が'ADD VALUE'の場合

insert into TABLE1 (ID,VALUE)

select

if(ID is NULL,0,max(ID))+1 as ID,

'ADD VALUE' as VALUE

from TABLE1 for update

を実行した時重複した場合エラーになり

PHPのmysql_errnoでエラーが重複エラー(1062)

ならSQLを再実行する。

http://dev.mysql.com/doc/refman/4.1/en/error-messages-server.htm...

id:rikimaru

色々あって面白いですね

非常に、興味深いです

2007/04/13 10:42:55
id:kurukuru-neko No.4

kurukuru-neko回答回数1844ベストアンサー獲得回数1552007/04/13 18:13:58

ポイント22pt

LOCK TABLEを使う場合、実際に更新が

発生するか参照系SQLは

select ... for update/lock in share modeの指定がないと完全には排他が機能しない。

今回の追加する最大シーケンス番号を

得るような目的だと

GET_LOCK/RELEASE_LOCK

でも実現可能

(テーブルには依存しない)

例:"TABLE1"は任意の文字,

  タイムアウト時間 100秒

select GET_LOCK("TABLE1",100);

更新処理のSQL

select RELEASE_LOCK("TABLE1");

今回の更新とは違いますが、比較的処理に

時間でかかっる処理を排他に実行したい

場合や、過負荷時の処理抑制にも応用出来る。

SELECT GET_LOCK("PROGRESS",xx);

戻り値が1である場合処理を実行

なので、何か排他的に実行したい処理を実行する。

戻り値が0の場合は誰か処理中

なので処理中で実行できないメッセージを

表示したり。本来タイムアウト時間以内に

処理が出来るのに出来ないのは、サーバ負荷

が非常に高いと判断して暫くしてから再実行

するようにメッセージを出す等の処理に

切替える。

戻り値がNULLの場合はエラー

http://dev.mysql.com/doc/refman/4.1/ja/miscellaneous-functions.h...

id:rikimaru

ちょっと読んでみますねー

ありがとうございます

2007/04/16 16:52:15

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません