<?phpinclude("config.inc.php");
$db=new db();
echo date('h:i:s') . "<br />";$db->execute("begin");$rs=$db->getRs("select * from book where sum>0 and id =1");
sleep(5);
if($rs->rowCount())//如果存在可借的书籍
    $db->execute("update book set sum=sum-1 where id =1");$db->execute("commit");echo date('h:i:s');?>
数据库为
CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sum` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbkinsert into book(sum) values(1); 我在火狐里运行一下,然后2秒后在ie里运行,最后book表的sum字段为-1了,直接在程序前后加上begin和commit并没有实现事务的功能,我试过在select 语句后加上for update ,执行后sum最后为0(符合我的 目的,)那我想问,对于复杂的事务,除了for update还有别的方法么

解决方案 »

  1.   

    检查一下你的MYSQL的autocommit 是什么值。
    SET autocommit=0; 后再试一下
      

  2.   


    改成$db->execute("set autocommit=0");
    $db->execute("begin");也没用,sum还是-1
      

  3.   

    用for update是最好的方法。
    innodb事务和其他数据库如SQL SERVER有点不一样。
    开启事务后, select语句并不会自动锁行(serializable隔离除外,但是加share锁),必须手工加share或exclusive锁。
    你的问题,必须加exclusive锁, 加share锁是没有用处,所以只能用for update
      

  4.   


    select for update 是加的拍它鎖吧,另外
    還有一個問題,select * from book where sum>0 and id =1 for upadte
    如果字段id沒有索引,將會把整個book表加鎖
      

  5.   

    說錯了,select for update 是加的共享鎖,別人還有讀的權限的,另外 
    還有一個問題,select * from book where sum>0 and id =1 for upadte 
    如果字段id沒有索引,將會把整個book表加鎖
      

  6.   

    我測試了下,在session1裏執行select * from book where sum>0 and id =1 for upadte,然後在session2執行select * from book where sum>0 and id =1,為什麼還可以讀到數據啊,session1不是加了排它鎖麼
      

  7.   

    是有点怪。
    for update
    对 for update ,lock in share mode,update,delete 起冲突,但对一般的select不冲突lock in share mode
    对 for update,update,delete 起冲突, 但对lock in share mode,一般的select不冲突