首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >悲观锁克主义

悲观锁克主义
EN

Stack Overflow用户
提问于 2015-02-03 23:16:38
回答 1查看 5.1K关注 0票数 2

设想情况:

我正在Symfony2中实现一个应用程序,它每5分钟运行一次命令(cronjob),该命令通过一个MySql表,在每条记录中,首先读取一个json_array字段,执行一系列计算,最后在同一个字段中使用新数据保存数组。此外,还有一个web应用程序,用户可以在该应用程序中编辑和保存同一表中的数据。

为了避免并发性,如果命令访问一条记录,我就会发出一个悲观的锁,这样,如果用户在那个时候更改数据,则必须等到事务结束,并在它完成时保存用户数据。

但是当用户保存数据时,随机存在一个错误,并且用户数据没有保存,web应用程序显示以前的数据,这表明锁不成功。

在symfony2命令中进行悲观锁的代码:

代码语言:javascript
复制
    foreach ($this->cisOfferMetaData as $oldCisOfferMeta) {
        // calculate budget used for each timeframe case and save it

        // begin transaction and Lock cisOfferMEta Entity
        $this->em->getConnection()->beginTransaction();
        try {
            $cisOfferMeta = $this->em->getRepository('CroboCisBundle:CisOfferMeta')->find(
                $oldCisOfferMeta->getId(),
                LockMode::PESSIMISTIC_READ
            );

            $budget = $cisOfferMeta->getBudgetOffer();

            foreach (
                generator(CisOfferMeta::getTypesArray(), CisOfferMeta::getTimeframesArray())
                as $type => $timeframe
            ) {
                if (isset($budget[$type][$timeframe]['goal'])) {
                    // if type=budget we need revenue value, if type=conversion, conversions value
                    $budget[$type][$timeframe]['used'] =
                        ($type === 'conversion')
                            ? intval($allTimeframes[$key]['conversions'][$timeframe])
                            : round($allTimeframes[$key]['revenue'][$timeframe], 2);

                    $budget[$type][$timeframe]['percent_reached'] =
                        ($budget[$type][$timeframe]['used'] == 0.0)
                            ? 0.0
                            : round(
                            $budget[$type][$timeframe]['used'] / intval($budget[$type][$timeframe]['goal']) * 100,
                            2
                        );
                }
            }

            $budget['current_conversions'] = $allTimeframes[$key]['conversions'];
            $budget['current_revenue'] = $allTimeframes[$key]['revenue'];

            $cisOfferMeta->setBudgetOffer($budget);

            $this->em->flush($cisOfferMeta);
            $this->em->getConnection()->commit();
        } catch (PessimisticLockException $e) {
            $this->em->getConnection()->rollback();
            throw $e;
        }

    }

我做错了什么吗?我想,由于事务是在修改完成后才启动的,如果用户试图读取或更新数据,则必须等到锁从被阻塞的实体中释放。

阅读Doctrine文档不清楚是否应该在实体中添加版本控制

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-07 09:57:58

最后,这段代码正常工作,并造成了悲观锁,问题在于侦听器在此锁之前读取数据,然后在释放锁后不进行任何更改地刷新数据。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28310623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档