php - 怎样理解mysql innodb的行级锁?

查看:110
本文介绍了php - 怎样理解mysql innodb的行级锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

因为最近在做公司的一个秒杀项目,就是现在一些购物网站最常见的那种。但是考虑到并发的一些问题(也许并发不是主要的,主要的是现在有秒杀就会出现秒杀工具之类的)导致被秒出去的商品比实际库存还要多,所以就上网看了一下mysql的锁,公司用的是innodb引擎,thinkphp3.2框架,根据网上的相关资料,应该用的是行级锁(对于mysql,本人菜鸟,懂的不是很深入)。

 public function test_sql(){
        set_time_limit(0);
        $model = D('Liren/GroupPurchase');
        $row = $model->lock(true)->where(array('id'=>1))->find();
        if($row){
            dump($row);
            sleep(10);
        }
    }

test_sql 方法是带锁查询了一条数据,之后延时了十秒,在这同时,我开了另一个进程:

 public function test_lock(){
        $model = D('Liren/GroupPurchase');
        $info = $model->find(1);
        if($info){
            dump($info);
        }
        
    }

在test_sql没有结束之前test_lock一直在等待。而且就算我在test_lock方法中查询的不是主键(id)为1的数据,也同样要等到test_sql结束之后才能执行。这样的话是不是整个表都锁住了,是不是需要继承thinkphp的AdvModel才能真正实现行级锁?

还有一个问题。事务和锁之间存在关系吗?

public function test_sql(){
        set_time_limit(0);
        $model = D('Liren/GroupPurchase');
        $model->startTrans();
        $row = $model->lock(true)->where(array('id'=>1))->find();
       // echo $model->getLastSql();
        if($row){
            $ret = $model->lock(true)->save(array('id'=>1,'is_show'=>0));
            echo $model->getLastSql();
        }
        if($ret){
            $model->commit();
            sleep(10);
            echo 'success';
        }
    }
    

虽然事务是提交了,数据库的状态也一早就改变了,但还是必须等到test_sql进程结束之后 test_lock 方法才能输出数据,如果能在事务结束的时候表锁就能结束,这样是不是好一点。

小弟愚钝,望指点!

解决方案

既然是秒杀功能为什么还要用MySQL呢?为什么不考虑redis等内存缓存数据库呢?
毕竟内存的IO效率和磁盘的IO效率之间大概相差了中美之间经济实力那么多吧

那么谈谈锁的问题:
相比题主现在对概念应该还有些模糊,我先明确概念:
读锁->共享锁 (S)
写锁 -> 排它锁 (X)

兼容性:

    X           S
X    不兼容    不兼容
S    不兼容    兼容

还有一种叫乐观锁/悲观锁

这份回答很好,我直接拿来了,总结来说就是:

  • △乐观锁是通过逻辑实现,本质上并没有给数据库加锁

  • 悲观锁是通过真实的数据库锁机制来完成的。

最后回到你的问题:

  • test_sql()函数: 首先要确认,在对表获取行锁的时候,要尽量的使用索引检索纪录,如果没有使用索引访问,那么即便你只是要更新其中的一行纪录,也是全表锁定的。要确保sql是使用索引来访问纪录的,必要的时候,请使用explain检查sql的执行计划,判断是否按照预期使用了索引。
    由于mysql的行锁是针对索引加的锁,不是针对纪录加的锁,所以虽然是访问不同行的纪录,但是如果是相同的索引键,是会被加锁的。

  • 事务和锁没什么关系,锁的机制与存储引擎才有关

这篇关于php - 怎样理解mysql innodb的行级锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆