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 级别保存对该记录的更改时,更新是有条件的,这意味着只有当前版本相同时才会进行更新。此更新还将版本增加一。

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

希望很清楚。

于 2012-06-04T18:01:25.137 回答
1

您还可以对服务器进行一些轮询,记录该行的最后一次更新,如果它发生变化,如果用户 B 在 A 之前更新记录,那么您可以通知用户 A 记录已更新并且他的更改不会生效,或者您可以动态更新值。

于 2012-06-04T18:06:50.550 回答
1

为此,您可以使用两个表。First -带有项目名称、ID 和计数的StockItems 。第二 -带有项目 id 和操作量的StockActivities 。

要从库存中添加或删除项目,您需要向第二个表StockActivities插入记录,其中包含添加/删除的项目 ID 和数量。

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

StockItems表的字段计数对于用户应该是“只读”的,并且应该基于StockActivities表计算。例如,您可以为StockActivities表创建后插入触发器,该触发器将更新添加/删除的库存项目的计数字段。

于 2012-09-20T10:27:44.240 回答
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 返回的数据中,我们可以知道受影响的行数。如果我们影响了一行,那么我们就成功地更新了它,工作就是我们的了。如果没有更新的行,那么另一台机器已经更新了它,并在那里声明了工作。

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

于 2016-07-18T21:23:08.353 回答