防守策略,我有一个小的PHP脚本,在一个表上 固定数量的每步行的工作,直到所有的行都被处理,以创建统计信息。用于锁定操作或避免并发数据处理
我不知道最好的策略是什么,以避免脚本的 SQL/DML语句的并发运行,如果我
- 只知道这是一个MySQL数据库的主要版本5
- 不知道是什么引擎被使用(MyISAM的或...)
- 只能保证数据库用户已经选择,插入,更新,删除权限
防守策略,我有一个小的PHP脚本,在一个表上 固定数量的每步行的工作,直到所有的行都被处理,以创建统计信息。用于锁定操作或避免并发数据处理
我不知道最好的策略是什么,以避免脚本的 SQL/DML语句的并发运行,如果我
InnoDB的是自动的:
在InnoDB中你不必在所有的任何锁定,如MySQL是在重复的读取事务隔离级别运行。当你开始一个事务然后选择一些东西时,第一个SELECT开始一个事务,并且因为这是可重复读取,所以你的数据视图将一直保持不变,直到你提交。
这意味着,首先,SELECT,SELECT,COMMIT InnoDB的重复读是SELECT,选择不同的。
的MyISAM是表锁:
在MyISAM中,你LOCK TABLES a, b, c READ, d WRITE
穿上你正在写在表上您正在阅读的表读锁和读/写锁。不可能用LOCK TABLES逐步建立一个锁列表,所以你必须一次性锁定你要触摸的所有东西,而且你无法触摸任何你没有锁定的东西,直到UNLOCK TABLES
。 LOCK TABLES需要一个额外的权限,并且在MyISAM中给出没有LOCK priv的SELECT权限是没有意义的。
一般是乐观锁定:
在MyISAM和InnoDB中没有交易,语句自动执行。这足以实现乐观锁定。在乐观锁定中,假设您有一个包含主键和数据的行。添加列state
和owner
。
[email protected] [kris]> create table d (id serial, d varchar(20), state enum('unclaimed', 'claimed', 'done') not null, owner integer unsigned not null);
Query OK, 0 rows affected (0.51 sec)
[email protected] [kris]> insert into d values (1, 'one', 'unclaimed', 0), (2, 'two','unclaimed', 0);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
[email protected] [kris]> select * from d;
+----+------+-----------+-------+
| id | d | state | owner |
+----+------+-----------+-------+
| 1 | one | unclaimed | 0 |
| 2 | two | unclaimed | 0 |
+----+------+-----------+-------+
2 rows in set (0.00 sec)
现在,您可以要求一个或多个行与您的处理器:
[email protected] [kris]> update d
set owner = 1, state = 'claimed'
where
state = 'unclaimed'
order by id limit 1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
警告称,这种说法并不安全的复制,但ORDER BY
应使LIMIT
安全的复制。其结果是,我们已经声称对与店主ID 1.这是在并发访问安全店主一排,因为被自动执行的UPDATE:
[email protected] [kris]> select * from d;
+----+------+-----------+-------+
| id | d | state | owner |
+----+------+-----------+-------+
| 1 | one | claimed | 1 |
| 2 | two | unclaimed | 0 |
+----+------+-----------+-------+
2 rows in set (0.00 sec)
我们需要选择回到我们目前正在努力,并对其进行处理:
[email protected] [kris]> select id, d from d where state = 'claimed' and owner = 1;
+----+------+
| id | d |
+----+------+
| 1 | one |
+----+------+
1 row in set (0.00 sec)
我们还需要将其设置为完成时,我们完成:
[email protected] [kris]> update d set state = 'done', owner = 0 where id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0