用于锁定操作或避免并发数据操作的防御策略
我有一个小型 PHP 脚本,它可以在表中的每个步骤处理固定数量的行 创建统计信息,直到处理完所有行。
我想知道避免脚本并发运行的最佳策略是什么 SQL/DML语句如果我
- 只知道它是MySQL数据库主要版本5
- 不知道使用什么引擎(MyISAM或...)
- 只能保证数据库用户具有SELECT,INSERT,UPDATE,DELETE权限
I have a small PHP script that works on a fixed number of rows per step in a table
to create statistics until all rows are processed.
I wonder what the best strategy is to avoid concurrent runs of the script's
SQL/DML-statements if I
- only know it's a MySQL database major release 5
- don't know what engine is used (MyISAM or ...)
- can only guarantee the database user has SELECT, INSERT, UPDATE, DELETE permissions
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
InnoDB 是自动的:
在 InnoDB 中你根本不需要锁定任何东西,因为 MySQL 运行在 REPEATABLE READ 事务隔离级别。当您开始一个事务,然后选择某些内容时,第一个 SELECT 就会启动一个事务,并且由于这是可重复读取,因此您对数据的视图将保持一致且不变,直到您提交为止。
这意味着InnoDB REPEATABLE READ中的BEGIN、SELECT、SELECT、COMMIT与SELECT、SELECT不同。
MyISAM 是表锁:
在 MyISAM 中,您需要 LOCK TABLES a, b, c READ, d WRITE 在您正在读取的表上放置读锁,并在您正在写入的表上放置读/写锁到。使用 LOCK TABLES 不可能增量地构建一个锁列表,因此您必须一次性锁定您将要触及的所有内容,并且在
UNLOCK TABLES
。 LOCK TABLES 需要额外的权限,并且在 MyISAM 中给予 SELECT 权限而不提供 LOCK 权限没有什么意义。通用的是乐观锁定:
在没有事务的MyISAM和InnoDB中,语句以原子方式执行。这足以实现乐观锁定。在乐观锁定中,假设您有一行包含主键和数据。将
state
和owner
列添加到其中。您现在可以为您的处理器声明一行或多行:
警告声明该语句对于复制来说不安全,但是
ORDER BY
应该使LIMIT
对于复制来说是安全的。结果是我们为所有者 id 为 1 的所有者声明了一行。这在并发访问中是安全的,因为更新是以原子方式执行的:我们需要选择回当前正在处理的内容,并处理它:
我们还完成后需要将其设置为完成:
InnoDB is automatic:
In InnoDB you'd not have to lock anything at all, as MySQL is running in REPEATABLE READ transaction isolation level. When you begin a transaction and then SELECT something, with the first SELECT a transaction is started and as this is REPEATABLE READ, your view of the data will be consistent and unchanging until you COMMIT.
This implies that BEGIN, SELECT, SELECT, COMMIT in InnoDB REPEATABLE READ is different from SELECT, SELECT.
MyISAM is table locks:
In MyISAM, you'd
LOCK TABLES a, b, c READ, d WRITE
to put read locks on the tables you are reading and read/write locks on the tables you are writing to. It is impossible to build a list of locks incrementally with LOCK TABLES, so you have to lock everything you are going to touch in one go, and you are unable to touch anything you did not lock until youUNLOCK TABLES
. LOCK TABLES requires an additional privilege, and it makes little sense to give SELECT priv without LOCK priv in MyISAM.Generic is optimistic locking:
In MyISAM and in InnoDB without transactions, statements are executed atomically. That is sufficient to implement optimistic locking. In optimistic locking, assume you have a row with a primary key and data. Add the columns
state
andowner
to it.You can now claim one or more rows for your processor:
The warning claims that this statement is not safe for replication, but the
ORDER BY
should make theLIMIT
safe for replication. The result is that we have claimed one row for the owner with the owner id 1. This is safe in concurrent access because an UPDATE is being executed atomically:We need to select back what we are currently working on, and process it:
We also need to set it to done when we are done: