3

php+mysqlを使って在庫管理システムを開発しようと思っています。これはサーバー マシン上で実行されるため、多くのユーザーが株式データを更新できます。(イン/アウト)

現在、このシステムに取り組んでいます。次の問題があります。

User A opens record “A”. ex- val=10
User B opens record “A”. ex - val=10
User A saves changes to record “A”. ex - val=10+2=12 (add 3 items, then stock should be 12)
User B saves changes to record “A”. ex - here i need to get record "A" value AS = 12, then B update val=12+3=15. (then add 3 items final stock will be 15)

In this example, User A’s changes are lost – replaced by User B’s changes.

mysql Innodb が行レベルのロックを容易にしていることは知っています。私の質問は、

innodb エンジンは同時制御を行います。これで(Innodb)「更新が失われる」問題を回避するのに十分です。または、この問題を回避するために追加のコーディングを行う必要があります。

これで十分ですか?前の例で innodb がどのように機能するか教えてください。(更新が失われました)

(私の悪い英語でごめんなさい)

ありがとう

4

5 に答える 5

2

InnoDB では同時アクセスが許可されているため、ユーザー Aユーザー Bは確実に同じデータを処理できます。ユーザー Aが自分のデータに基づいて行を更新すると、ユーザー Bも同じことを実行できます。最終的にはユーザー Aのデータが失われます。

すべての更新を保持することが不可欠である場合は、別の方法を検討する必要があります。たとえば、両方のユーザーがブログ記事を更新している場合、これらすべての編集を保持する新しいテーブルを作成できます。両方のユーザーの編集内容は、記事のコンテンツを取得したときでも保持されます。記事が取得されると、最新の編集がいつ行われたかを確認し、代わりにそれを取得できます

于 2012-06-04T17:59:04.913 に答える
2

ほら、「バージョン管理」と呼ばれるものがあります。

アイデアは単純です。
ユーザーがレコードを開くと、バージョン番号も取得します。
彼がそのレコードへの変更を保存すると、SQL レベルで更新は条件付きになります。つまり、現在のバージョンが同じ場合にのみ更新が行われます。この更新により、バージョンも 1 つ増えます。

この方法により、レコードの「古い」コピーに書き込んでいないことが保証されます。

それが明確であることを願っています。

于 2012-06-04T18:01:25.137 に答える
1

この目的のために2つのテーブルを使用できます。最初-アイテム名、ID、およびカウントを持つStockItems 。2番目-アイテムIDと操作量を持つStockActivities 。

在庫にアイテムを追加または削除するには、追加/削除されたアイテムIDと数量を含むレコードを2番目のテーブルStockActivitiesに挿入する必要があります。

    item id:1, qnt: +10
    item id:1, qnt: +1
    item id:10, qnt: -2

StockItemsテーブルのフィールドは、ユーザーに対して「読み取り専用」であり、 StockActivitiesテーブルに基づいて計算する必要があります。たとえば、追加/削除された在庫アイテムのカウントフィールドを更新するStockActivitiesテーブルの挿入後トリガーを作成できます。

于 2012-09-20T10:27:44.240 に答える
1

また、サーバーへのポーリングを実装し、行の最後の更新の記録を保持し、ユーザー B が A の前にレコードを更新した場合に変更された場合、ユーザー A にレコードが更新されたこと、および彼の変更が行われないことを通知できます。または、値を動的に更新できます。

于 2012-06-04T18:06:50.550 に答える
0

残されたコメントから判断すると、誰かが必要な場合に備えて、私が遭遇したいくつかの指針で応答することが賢明だと思います.

オフセットによって値を更新するだけの場合は、これを非常に簡単かつアトミックに行うことができます。次のデータを想定します。

+----+--------+-------+
| id | name   | price |
+----+--------+-------+
| 1  | Foo    | 49    |
| 2  | Bar    | 532   |
| 3  | Foobar | 24    |
+----+--------+-------+

次のクエリを実行して、価格に 1 を追加できます。

select id, price from prices where name like "Foo";
// Later in the application
update prices set price=50 where id=1;

これは、2 つのクエリ間に変更やフェッチがないことを前提として、これを実行するための非並行/非アトミックな方法です。これを行うためのよりアトミックな方法は次のとおりです。

select id, price from prices where name like "Foo";
// Later in the application
update prices set price=price+1 where id=1;

ここで、このクエリにより、1 つのクエリで価格をインクリメントできるため、2 つのクエリ間で他のユーザーが来て更新することができなくなります。

さらに、更新の性質が単純な加算または減算ではない場合に、データを安全に更新する方法があります。ここで、次のデータがあるとします。

+----+----------+---------------------+
| id | job_name | last_run            |
+----+----------+---------------------+
| 1  | foo_job  | 2016-07-13 00:00:00 |
| 2  | bar_job  | 2016-07-14 00:00:00 |
+----+----------+---------------------+

この場合、複数の異なるクライアントがあり、すべてのクライアントが任意のジョブを実行できます。次に、1 つのクライアントだけに作業をディスパッチする方法が必要です。

レコードが更新された場合にエラーが発生するトランザクションを使用するか、CAS と呼ばれる手法を使用するか、Compare and Swap を使用できます。

MySQL でこれを行う方法は次のとおりです。

update jobs set last_run=NOW() where id=1 and last_run='2016-07-13 00:00:00'

次に、mysql から返されたデータで、影響を受けた行の数がわかります。行に影響を与えた場合、それは正常に更新されており、ジョブは私たちのものです。行が更新されていない場合は、別のマシンが更新し、そこでジョブを要求しています。

これが機能するのは、アプリケーションからの更新によって列が変更されるためです。また、列の値は更新を完了するための条件であるため、同時変更が回避され、次に何が発生するかをアプリケーションが決定できるようになります。

于 2016-07-18T21:23:08.353 に答える