0

行に対して2つの更新を行う必要がありますが、それらが一緒に行われ、別のユーザーからの他のクエリがそれらに干渉しないことを確認する必要があります。私は知ってSELECT...FOR UPDATEいますが、最初の更新後はもちろんロックが解除されると思います。つまり、誰かが2番目の更新を妨害する可能性があります。他の誰かが最初にその行を更新した場合、更新は機能しますが、データを台無しにします。とにかく、2つの更新が想定どおりに行われるようにする方法はありますか?トランザクションについて聞いたことがありますが、私が誤解してトランザクションがコミットされるまで行がロックされない限り、2つの更新が実際に発生することを確認するだけで、「一緒に」発生するかどうかはわかりません。

クエリは次のとおりです。

SELECT z FROM table WHERE id='$id'

UPDATE table SET x=x+2 WHERE x>z

UPDATE table SET y=y+2 WHERE y>z

私は間違いを犯し、完全な情報を提供しませんでした。それが私のせいでした。クエリを更新しました。私が抱えている問題は、zも更新できるということです。SELECTの後、他の2つの更新の前にzが更新されると、データが混乱する可能性があります。トランザクションBEGIN/COMMITを実行すると、そのために機能しますか?

4

3 に答える 3

0

TRANSACTION について学ぶ http://dev.mysql.com/doc/refman/5.0/en/commit.html

[... connect ...]

mysql_query("BEGIN");

$query1 = mysql_query('UPDATE table SET x=x+2 WHERE x>y');
$query2 = mysql_query('UPDATE table SET y=y+2 WHERE y>y');

if($query1 && $query2) {
    mysql_query("COMMIT");  
    echo 'Save Done. All UPDATES done.';  
} else {
    mysql_query("ROLLBACK");  
    echo 'Error Save. All UPDATES reverted, and not done.';  
}
于 2012-04-08T03:54:59.440 に答える
0

1 つのアプローチは、テーブル全体をロックすることです。

LOCK TABLE `table` WRITE;
SELECT z FROM `table` WHERE id='$id';
UPDATE `table` SET x=x+2 WHERE x>z;
UPDATE `table` SET y=y+2 WHERE y>z;
UNLOCK TABLES;

tableこれにより、SELECT および UPDATE 中に、他のセッションがテーブルから書き込みおよび読み取りを行うことができなくなります。

これが適切な解決策であるかどうかは、セッションがテーブルからの読み取りまたは書き込みを待機することがどれほど適切であるかによって異なります。

于 2012-04-08T07:44:04.133 に答える
0

トランザクションにはさまざまなレベルがありますが、基本的にACIDプロパティに従って、特定のトランザクション内ですべての読み取りと更新が一貫して実行されることを期待する必要があります。別のトランザクション (スレッド) で実行されても、トランザクション (select および update SQL ステートメントのグループ化) に干渉しません。これにより、システム内で実行の唯一のスレッドであるという広範な想定を行うことができ、そのグループのコミットを許可します。 (アトミックに)動作するか、すべてロールバックします。

各データベースはセマンティクスを異なる方法で処理する場合があります (行または列をロックするもの、順序を変更するもの、シリアライズするものがあります) が、それが宣言型データベース インターフェースの利点です。

前述のように、MySQL では InnoDB はトランザクション対応であり、上記をサポートするため、テーブルが InnoDB で編成されていることを確認してください。他の非トランザクション エンジン (MyISAM など) はトランザクション対応ではないため、これらのトランザクション セマンティクス (ロック) を手動で管理する必要があります。 .

于 2012-04-08T04:08:46.603 に答える