解决高并发下insert到数据库表多条记录的问题

简介: 解决高并发下insert到数据库表多条记录的问题

1.有种业务场景比如微信会员注册,我们首先判断openid在数据库表中是否存在如果存在则提示已经存在,否则注册一条会员记录。thinkphp5代码如下


        $openid  =  '1111111' ;

        //查询openid是否存在

        $info =  Db :: table (  'test'  )-> where (  'openid' ,  $openid  )-> find ();

        if  (! empty ( $info )) {

            echo   'openid已经存在!' ;

            die ;

       }

        sleep ( 2 );  //模拟其他复杂业务逻辑处理增加耗时

        //insert插入

        $data [ 'openid' ] =  $openid ;

        $data [ 'add_time' ] =  date (  'Y-m-d H:i:s' ,  time () );

        $rs = Db :: table (  'test'  )-> insert (  $data  );

        print_r ( $rs );

        die ;

我相信这样的场景有很多,而且大家也都写过类似的代码,而且看上去也在正常不过了,但是这样的代码在高并发的情况下会插入数据库表多条记录。


我用apache jmeter压测工具模拟50个并发请求,然后发现数据库进来25条记录。问题出现了。

1.jpg

上面代码sleep(2);是为了模拟注册过程中其他的一些业务逻辑处理。如果没有sleep(2),我用apache jmeter工具并发请求,也没有发现出来多条记录。那么如果解决上面的问题呢?引入mysql锁的概念。锁必须与事务配合使用下面是改进的代码 :


        $openid  =  '1111111' ;

        // 启动事务

        $trans_result  =  true ;

        Db :: startTrans ();

        try  {

            //查询openid是否存在  ,//查询之后锁住该条记录让其他程序无法修改,直到事务提交释放锁

            $info  =  Db :: table (  'test'  )-> lock (  true  )-> where (  'openid' ,  $openid  )-> find ();

            if  ( ! empty (  $info  ) ) {

                //手动抛出异常

                throw   new   \Exception (  'openid已经存在!'  );

           }

            sleep (  2  );

            //模拟其他复杂业务逻辑处理增加耗时

            //insert插入

            $data [ 'openid' ] =  $openid ;

            $data [ 'add_time' ] =  date (  'Y-m-d H:i:s' ,  time () );

            $rs  =  Db :: table (  'test'  )-> insert (  $data  );

            if  ( ! $rs  ) {

                //手动抛出异常

                throw   new   \Exception (  'insert 失败!'  );

           }

            Db :: commit ();

       }  catch  ( \ Exception   $e  ) {

            // 回滚事务

            Db :: rollback ();

            $trans_result  =  false ;

            echo    $msg  =  $e -> getMessage ();

       }

        //如果失败

        if  ( ! $trans_result  ) {

            echo   '执行失败0' . $msg ;

       } else  {

            echo   '执行成功1' ;

       }


2.jpg

2.jpg8.jpg9.jpg

总结,把查询语句和插入语句放到一个事务里面,解决不了并发插入多条记录的问题,还需要配置使用锁,锁的意思就是当n个请求同时过来只有一个人能获取到锁,并且锁住那条记录,其他程序无法获取到就会报错,也就是这么多并发请求,最终只有一个能够执行成功。当然此案例也可以使用mysql表openid字段设置唯一索引,50个并发最终也会只有一个能成功,其他的同样会抛出sql异常。


相关文章
|
18天前
|
JavaScript 数据库
❤Nodejs 第七章(操作本地数据库高并发createPool方式)
【4月更文挑战第7天】本文介绍了如何使用Node.js操作本地数据库接口的优化,将之前的单次连接(createConnection)替换为支持高并发的连接池(createPool)。主要改动包括:查询、新增用户、获取用户详情、更新和删除用户的方法,都改用`connectionpool.query()`。这样改进能提升效率,适应更多并发请求。代码示例展示了如何在路由处理函数中使用连接池进行数据库操作。
86 6
❤Nodejs 第七章(操作本地数据库高并发createPool方式)
|
18天前
|
关系型数据库 MySQL 数据库连接
Python+SQLite数据库实现服务端高并发写入
Python中使用SQLite内存模式实现高并发写入:创建内存数据库连接,建立表格,通过多线程并发写入数据。虽然能避免数据竞争,但由于SQLite内存模式采用锁机制,可能在高并发时引发性能瓶颈。若需更高性能,可选择MySQL或PostgreSQL。
63 0
|
18天前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
7月前
|
数据库
高并发下数据库插入常见的问题
高并发下数据库插入常见的问题
34 0
|
10月前
|
缓存 NoSQL 应用服务中间件
高并发场景下的redis缓存和数据库双写不一致问题分析与解决方案设计
高并发场景下的redis缓存和数据库双写不一致问题分析与解决方案设计
|
10月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
10月前
|
算法 NoSQL Java
2021年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
10月前
|
关系型数据库 测试技术 分布式数据库
PolarDB | PostgreSQL 高并发队列处理业务的数据库性能优化实践
在电商业务中可能涉及这样的场景, 由于有上下游关系的存在, 1、用户下单后, 上下游厂商会在自己系统中生成一笔订单记录并反馈给对方, 2、在收到反馈订单后, 本地会先缓存反馈的订单记录队列, 3、然后后台再从缓存取出订单并进行处理. 如果是高并发的处理, 因为大家都按一个顺序获取, 容易产生热点, 可能遇到取出队列遇到锁冲突瓶颈、IO扫描浪费、CPU计算浪费的瓶颈. 以及在清除已处理订单后, 索引版本未及时清理导致的回表版本判断带来的IO浪费和CPU运算浪费瓶颈等. 本文将给出“队列处理业务的数据库性能优化”优化方法和demo演示. 性能提升10到20倍.
622 4
|
11月前
|
存储 NoSQL 算法
高并发设计系列-数据库篇
高并发设计系列-数据库篇
|
缓存 监控 网络协议
并发编程-26 高并发处理手段之服务降级与服务熔断 + 数据库切库分库分表
并发编程-26 高并发处理手段之服务降级与服务熔断 + 数据库切库分库分表
77 0

热门文章

最新文章