防止同时进行数据库表行访问
-
28-10-2019 - |
题
有时,我们支持团队中的两个管理员试图对数据库表行执行相同的敏感操作(例如,修改行中的值)。我们需要防止这种情况。 (因为表是“ myisam”,所以行锁定是不可能的)
我想到了几种解决方案:
在表格中设置旧值并将其与提交时的当前值进行比较 通用标签
然后在更新之前: 通用标签
但可能存在以下情况:
-
用户需要将钱值从9 $更改为10 $
-
admin1将他的钱更改为10 $
-
用户明智地花费1美元,因此他目前的钱又变成了9美元!
-
admin2在没有警告的情况下将他的钱改为10美元。
在行中创建时间戳记(updated_at列)
并与解决方案1相同。这样做的好处是,它比简单的数据比较更具优势。我们可以肯定地说,在摆弄表格时是否更改了数据。缺点-除非将其与解决方案1结合在一起,否则我们无法跟踪确切更改了哪一列 通用标签
然后在更新时: 通用标签
使用对象/动作专用名称创建长度为0的临时文件
在更新期间创建/锁定它,并检查其 更新之前存在/日期戳。
更新前: 通用标签
就目前而言,文件创建是我的首选方法,因为:
-
我认为创建本地文件比访问数据库更快。
-
我不需要在表中再添加一列(时间戳)
-
我可以轻松地修改文件名以检查特定的列修改,即在完成mysqlupdate后创建文件“ money_user {$ userid} _modified”。
是对的还是我误会了什么?
-
解决方案
您可以在UPDATE
操作的WHERE
子句中指定旧值,然后查看受影响的行数:
给予 通用标签
线程1执行 通用标签
线程2执行 通用标签
除此之外,为了减少浪费的时间,我可能会更早地实现排除,方法是先将任务分配给各个管理员。
其他提示
在您的情况下,我认为锁定是最好的方法。您可以使用MySQL锁定: GET_LOCK,RELEASE_LOCK,IS_FREE_LOCK。我认为事务不能保证在另一个进程对获取的数据执行其任务时,行不会发生更改。
尽管,您的特殊情况与传统意义上的锁定无关。恕我直言,您需要使用相应的凭据和描述记录您的交易,以便您的管理员可以读取它们,而不必复制相同的余额修改。锁可以防止同时修改行,但不能防止在配音时故意更改。
我认为数据库的行级锁定无法满足您在第一种方法中提到的情况。但是我也不认为文件创建比访问数据库系统要快。在数据库上,文件创建显然比CRUD重。
因此,我建议对日志表使用类似的方法。
- 每个表都有自己的主键(例如
pid
) - 当有人试图摆弄一行时,将带有时间戳的表名和pid记录到日志表中。
- 在运行查询之前检查日志表。
看看InnoDB和事务。它们更适合敏感变化(即平衡)。
数据库通常更好,因为它们是集中式解决方案。如果由于流量或工作量大而必须扩展,则同步这些文件并不容易。除非您不期望有任何扩展需求并且I / O速率很好,否则就可以。
请允许我提及两种可能的解决方案,您可能在上面也提到过。
您可以添加一个“ assigned_id”,其中包含您的管理员帐户的ID和时间戳,以便您的应用程序在其他人对其进行编辑时显示警告。
另一种可能的解决方案是在填写表格时检查是否进行了任何更改。可以在这里使用经过最后编辑的时间戳。