11

更新:MysqlとPostgresSKIP LOCKEDがあります。NOWAIT

古い質問が続きます。


並行トランザクションでテーブルから行を選択し、他のトランザクションが選択できないように「ダーティ」としてマークしてから、残りのトランザクションを実行するようにします。

select... for update2番目のトランザクションが同じことを主張しているため、この目的で使用するのに問題がありました。個別の行を選択するためのさまざまなトランザクションの最小限の例を提供してください。

私のデータは次のとおりです。

mysql> select * from SolrCoresPreallocated;
+----+-------------+-----+-----+
| id | used_status | sid | cid |
+----+-------------+-----+-----+
|  1 |           0 |   0 | 400 |
|  2 |           0 |   0 | 401 |
|  3 |           0 |   0 | 402 |
|  4 |           0 |   0 | 403 |
|  5 |           0 |   0 | 404 |
|  6 |           0 |   0 | 405 |
+----+-------------+-----+-----+
6 rows in set (0.00 sec)

そして、このようなものは期待どおりに機能していません:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from SolrCoresPreallocated order by id limit 1 for update;
+----+-------------+-----+-----+
| id | used_status | sid | cid |
+----+-------------+-----+-----+
|  1 |           0 |   0 | 400 |
+----+-------------+-----+-----+
1 row in set (0.00 sec)

...set the used_status to 1
...perform the rest of the operations

...2番目以降のトランザクションとして

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from SolrCoresPreallocated order by id limit 1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>  rollback;
Query OK, 0 rows affected (0.00 sec)
4

1 に答える 1

12

SELECT ... FOR UPDATE行を排他モードでロックします。これは、最初の選択が完了するかロールバックされるまで、2番目の選択を続行できないことを意味します。これは、2番目の選択の結果が、ロックした行の内容の影響を受ける可能性があるためです。そのため、チェックするには、行の読み取りロックを取得する必要があります。

UNIQUE INDEXたとえば、onを作成するとid、次のことができます。

select * from SolrCoresPreallocated where id=1 for update;

最初のトランザクションで;

select * from SolrCoresPreallocated where id=2 for update;

一意のインデックスにより、2番目のselectは、最初の行をリードロックせずに正しい行を見つけることができるため、2番目の行では独立しています。

編集:「無料」の行をできるだけ早く取得するには、実際には2つのトランザクションを実行するしかありません。

  • 行を取得するには、BEGIN / SELECT FOR UPDATE/UPDATEからbusy/COMMITへ。
  • BEGIN/<行の処理>/UPDATEで解放/COMMITで行を処理して解放します。

これは、プロセスが失敗し、行を解放するように更新するトランザクションをロールバックする場合に補償アクションが必要になる可能性があることを意味しますが、MySQL(またはそのことについては標準SQL)には「次のロック解除された行を取得する」という概念がないため"、あなたには多くの選択肢がありません。

于 2012-10-06T10:16:21.793 に答える