并发多用户访问php + mysql

时间:2012-06-04 17:48:20

标签: php mysql innodb

我将使用php + mysql开发Stock维护系统。它将在服务器机器上运行,因此许多用户可以更新库存数据。 (进/出)

我目前正在研究这个系统。我有以下问题。

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如何与我之前的例子一起使用。 (丢失更新)

(抱歉我的英语不好)

感谢

5 个答案:

答案 0 :(得分:2)

InnoDB允许并发访问,因此用户A 用户B 绝对可以处理相同的数据。 用户A 会根据他/她的数据更新该行,然后用户B 也可以这样做 - 最终会导致用户A 数据丢失。

如果每次更新都至关重要,您应该考虑替代方案。例如,如果两个用户都在更新博客文章,您可以创建一个包含所有这些编辑的新表。尽管他们检索了文章内容,但两个用户的编辑都会被保留。检索文章后,您可以检查最近的编辑发生的时间,然后检索

答案 1 :(得分:2)

看,有一种叫做“版本化”的东西。

这个想法很简单:
当用户打开记​​录时,他也会获得版本号 当他将更改保存到该记录时,在sql级别,更新是有条件的,这意味着只有当前版本相同时才会进行更新。此更新还将版本增加一个。

这样可以确保您不会写入记录的“陈旧”副本。

希望很清楚。

答案 2 :(得分:1)

你也可以对服务器实施一些轮询,记录行的最后一次更新,如果用户B在A之前更新记录,它会改变,那么你可以通知用户A记录已经更新了他的更改不会生效,或者您可以动态更新值。

答案 3 :(得分:1)

您可以使用两个表来实现此目的。首先 - StockItems ,包含项目名称,ID和计数。第二 - StockActivities ,包含商品ID和操作金额。

要添加或删除库存中的商品,您需要将记录插入第二个表 StockActivities ,并添加/删除商品ID和数量。

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

StockItems 表的字段计数应为用户“只读”,并应根据 StockActivities 表进行计算。 例如,您可以为 StockActivities 表创建插入触发器后,这将更新已添加/删除的库存项目的计数字段。

答案 4 :(得分:0)

根据留下的评论判断,我认为谨慎回应我遇到的一些指示,以防有人需要。

如果您只想通过偏移量更新值,则可以非常轻松且原子地执行此操作。假设以下数据:

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

我们现在可以运行以下查询以在价格中添加一个:

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

这是执行此操作的非并发/非原子方式,假设两个查询之间没有更改或提取。更为原子的方法是:

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

在这里,此查询允许我们在一个查询中增加价格,从而消除了其他人在两个查询之间进行更新的能力。

此外,还有一些安全更新数据的方法,其中更新的性质不是简单的加法或减法。我们在这里说,我们有以下数据:

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

在这种情况下,我们有多个不同的客户端,所有客户端都可以完成任何工作。然后,我们需要一种方法将工作分配给一个客户端,并且只需一个客户端。

我们可以使用一个交易,如果记录已经更新,我们会报错,或者我们可以使用一种名为CAS的技术,或比较和交换。

以下是我们在MySQL中的表现:

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

然后,在mysql返回的数据中,我们可以告诉受影响的行数。如果我们影响了一行,那么我们已成功更新它,并且工作是我们的。如果没有更新行,则另一台机器已更新它,声称在那里工作。

这是有效的,因为我们的应用程序的任何更新都会导致列发生更改,并且由于列的值是完成更新的条件,因此它将避免并发更改,从而允许应用程序决定接下来会发生什么。