thinkphp3 数据库锁的使用与研究

5 篇文章 0 订阅
2 篇文章 0 订阅

最近项目涉及到了一个有可能出现并发的功能,因此网上查询了一下有关于tp3表锁的知识,可惜都不是非常详细,因此决定自己来进行一次测试。

 

情况一:两进程查询同一条记录,不加锁

 public function testLock()
    {
        $uuid = I('uuid');
        $result = M('purchase_detail', 'iwh_')->where(['uuid' => $uuid])->find();//根据uuid查找某条记录
        sleep(10);//休眠10秒
        $this->successAjaxReturn("运行结束");//返回结果

    }

用python模拟查询,最后得出结果:两个进程均运行10秒,互不干扰。

情况二:两进程查询同一条记录,加锁

 public function testLock()
    {
        $uuid = I('uuid');
        $result = M('purchase_detail', 'iwh_')
            ->lock(true)->where(['uuid' => $uuid])
            ->find();//根据uuid查找某条记录
        sleep(10);//休眠10秒
        $this->successAjaxReturn("运行结束");//返回结果

    }

结果:依旧互不干扰

情况三:两进程查询同一条记录,加锁,停留10秒,随后对该记录进行修改,进程1,将记录修改为test1,进程2将备注字段修改为test2。

​

 public function testLock()
    {
        $uuid = I('uuid');
        $result = M('purchase_detail', 'iwh_')
            ->lock(true)->where(['uuid' => $uuid])
            ->find();//根据uuid查找某条记录
        sleep(10);//休眠10秒
        $this->successAjaxReturn("运行结束");//返回结果

    }

结果:互不干扰,备注最终变为test2

情况4:两个进程在事务下查询同一个记录

 public function testLock1()
    {
        $uuid = I('uuid');//uuid
        $model = new Model();
        $model->startTrans();
        $result = M('purchase_detail', 'iwh_')->lock(true)->where(['remark' => $uuid])->find();
        sleep(10);
        $model->commit();
        $this->successAjaxReturn("运行结束");

    }

结果:进程1执行了10秒,进程2执行了20秒,说明进程2在等待进程1的执行。

从以上结果我们可以推断出,加锁语句必须放在事务中才能起作用。

 

情况5:两个进程在事务下查询不同记录

结果同上,说明出现了锁表的情况,而非锁行。

这个时候突然想到,我用的引擎是默认MyISAM引擎,好像不支持锁行?

20191129143505440.png

更换一下试试。

打开配置文件my.ini,将"default-storage-engine=MYISAM"修改为"default-storage-engine=innodb"

查看一下,确认有修改成功

20191129144011573.png

测试结果:在查询不同行的情况下,依旧发生了阻塞。

好吧,tp3行级锁究竟应该怎么用呢?用原生语句试试!

  public function testLock1()
    {
        $uuid = I('uuid');//uuid
        M('purchase_detail','iwh_')->startTrans();
//        $result = M('purchase_detail', 'iwh_')->lock(true)->where(['remark' => $uuid])->find();
        $sql = sprintf("select * from iwh_purchase_detail where  uuid = '%s' for update ",$uuid);//查询语句
        M()->execute($sql);
        sleep(10);
        M('purchase_detail','iwh_')->commit();
        $this->successAjaxReturn("运行结束");

    }

 

测试结果:成功触发行级锁!在查询不同行时,没有相互堵塞。在查询同一行时,代码发生了堵塞的情况!

总结:

1、 要想触发mysql的锁机制,必须将触发语句放入到事务处理之中。

2、tp3的框架语句只能触发表级锁,而无法触发行级锁。

2、要想触发mysql的行级锁,必须用执行原生语句的方式,并且要将数据库引擎换成innodb

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值