2011-04-07 27 views
0

防守策略,我有一个小的PHP脚本,在一个表上 固定数量的每步行的工作,直到所有的行都被处理,以创建统计信息。用于锁定操作或避免并发数据处理

我不知道最好的策略是什么,以避免脚本的 SQL/DML语句的并发运行,如果我

  1. 只知道这是一个MySQL数据库的主要版本5
  2. 不知道是什么引擎被使用(MyISAM的或...)
  3. 只能保证数据库用户已经选择,插入,更新,删除权限

回答

1

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中没有交易,语句自动执行。这足以实现乐观锁定。在乐观锁定中,假设您有一个包含主键和数据的行。添加列stateowner

[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