我将使用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如何与我之前的例子一起使用。 (丢失更新)
(抱歉我的英语不好)
感谢
答案 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返回的数据中,我们可以告诉受影响的行数。如果我们影响了一行,那么我们已成功更新它,并且工作是我们的。如果没有更新行,则另一台机器已更新它,声称在那里工作。
这是有效的,因为我们的应用程序的任何更新都会导致列发生更改,并且由于列的值是完成更新的条件,因此它将避免并发更改,从而允许应用程序决定接下来会发生什么。