请问:如何锁定一条记录?

#1 tmd

当我想修改数据库表中的一条记录时,怎样锁住它,不允许其他函数或进程对此记录操作,等到修改完成后才允许其他的函数或进程对此记录操作?

2011-04-16 22:38:28

#2 jake

用SQL

http://speedphp.com/model-sql-usage.html

2011-04-17 09:45:58

#3 tmd

回复 2 jake

我查了一下mysql手册,讲的太复杂不好懂。查网上说是使用了事务处理的话会自动锁定。
我想问的是我要同时操作多张表,是不是需要每个表启用一次事物呢?就类似下面这样:

$tradelog=spClass("tradelog");
$Orderlog=spClass("Orderlog");
$autotask=spClass("autotask");
$users = spClass("users");

$users->query("START TRANSACTION"); // 或者是$g->query("BEGIN");
$tradelog->query("START TRANSACTION"); // 或者是$g->query("BEGIN");
$Orderlog->query("START TRANSACTION"); // 或者是$g->query("BEGIN");
$autotask->query("START TRANSACTION"); // 或者是$g->query("BEGIN");

。。。。

   $tradelog->query("COMMIT");  // 没有问题,那么事务提交。
   $Orderlog->query("COMMIT");  // 没有问题,那么事务提交。
   $autotask->query("COMMIT");  // 没有问题,那么事务提交。



这样写是不是太多余了?还有这能够防止此期间别的进程对其中某个表操作吗(别的进程修改肯定不行,查询也要等待修改完成后进行)?

2011-04-18 20:46:37

#4 jake

这里可能你对锁定的概念有些误解了,锁定有两个必要条件:高并发和非原子操作,才需要锁定。

单独一条SQL语句的修改(UPDATE,DELETE,INSERT都是),那是原子操作(或者说成一次性操作),那么在进行这些操作的时候,数据库会自动锁表(有些会局部锁),保证不受干扰。

事务是“非原子操作”的情况下,保证数据正确的措施。同个数据库链接(model基本都是用同一个),BEGIN一次和COMMIT一次就算一个事务,那是不分区分哪个表的。也就是不需要三个那么多。

2011-04-18 23:21:54

#5 tmd

谢谢老大详细解释!还有一个疑问待确定:事务这能够防止此期间别的进程对其中涉及的某个表操作吗?比如我在事物当中要同时修改tradelog、Orderlog、autotask、users表;同时另一个用户可能也在修改users、tradelog、Orderlog这些表中的同一条记录;有没有可能互相冲突,导致不想要的结果?
另外,select * from table for update 这样用于锁定的句子只能直接使用sql语句,没有现成的函数可以用对吗?

2011-04-23 20:45:01

#6 jake

当你在操作tradelog、Orderlog、autotask、users任一个表的时候,这个表都是锁定的,至少等操作完成之前,另一用户是不能修改记录的(可读可不读,这是数据库自行判断的),所以不会有你想象的问题存在。

另外,目前的数据库驱动,比教科书上面说的智能多了,现在已经可以自行判断你的操作然后执行表锁定或者行锁定之类的操作,我们实践开发中很少需要考虑到锁的问题。教科书上面说锁的问题,那是90年代的事情。

目前在考虑数据库方面的事情,更多的是考虑用集群的方式来做负载均衡,以应对同时并发的大数据量大访问量的问题。

用sql语句不好吗?别的人看你代码的时候,只需要理解sql语句,而不需要理解一堆古怪的封装函数(一个函数当然实现不了,在别的一些框架里面,这种操作是一堆函数)。

2011-04-23 21:26:42

#7 tmd

谢谢老大!冰释了我的后顾之忧。现在的资料不是太少而是太多,看的迷惑,就缺老大这一点睛之言啊!

2011-04-24 12:48:55