Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 错误';没有等待锁';使用Yii2队列扩展和Postgres 10.4_Php_Postgresql_Yii2_Queue_Locking - Fatal编程技术网

Php 错误';没有等待锁';使用Yii2队列扩展和Postgres 10.4

Php 错误';没有等待锁';使用Yii2队列扩展和Postgres 10.4,php,postgresql,yii2,queue,locking,Php,Postgresql,Yii2,Queue,Locking,我在yii2中开发了一个项目,它使用yiisoft/yii2队列扩展。此扩展存储用于导出非常大的CSV的订单。 导出的CSV工作正常,但有时会抛出映像异常: 我想这可能是因为我使用的postgres版本:x86_64-pc-linux-gnu上的PostgreSQL 10.4(Debian 10.4-2.pgdg90+1),由gcc(Debian 6.3.0-18+deb9u1)6.3.0 20170516编译,64位 我读过9.4版的文章,它可以工作。 我拥有的扩展配置如下所示: 'compo

我在yii2中开发了一个项目,它使用yiisoft/yii2队列扩展。此扩展存储用于导出非常大的CSV的订单。 导出的CSV工作正常,但有时会抛出映像异常:

我想这可能是因为我使用的postgres版本:x86_64-pc-linux-gnu上的PostgreSQL 10.4(Debian 10.4-2.pgdg90+1),由gcc(Debian 6.3.0-18+deb9u1)6.3.0 20170516编译,64位

我读过9.4版的文章,它可以工作。 我拥有的扩展配置如下所示:

'components' => [
    'queue' => [
        'class' => \yii\queue\db\Queue::class,
        'tableName' => '{{%queue}}', // Table name
        'channel' => 'default', // Queue channel key
        'db' => require(__DIR__ . '/db.php'),
        'mutex' => [
            'class' => \yii\mutex\PgsqlMutex::class,
            'db' => require(__DIR__ . '/db.php'),
        ],
        'mutexTimeout' => 0,
    ],
]
有人知道为什么会发生此错误以及如何修复它吗

这可能就是原因。这意味着队列将尝试获取互斥锁一次,如果失败(在繁忙队列上很可能失败),它将抛出此异常


PgsqlMutex
中支持超时,但尚未发布此功能。我建议使用
yiisoft/yii2
包的
master
分支,并将
mutexTimeout
设置为非零值。

通过在供应商/yiisoft/yii2队列/src/drivers/db/queue.php中更改两种方法来修复它 代码:

/**
*@param数组$payload
*/
受保护功能释放($payload)
{
$mutex=$this->mutex->acquire($this->channel,$this->mutexTimeout);
试一试{
如果($this->deleteReleased){
$this->db->createCommand()->删除(
$this->tableName,
['id'=>$payload['id']]
)->执行();
}否则{
$this->db->createCommand()->更新(
$this->tableName,
['done_at'=>time()],
['id'=>$payload['id']]
)->执行();
}
}捕获(例外$e){
\Yii::error($e->getMessage());
}最后{
如果($mutex){
$this->mutex->release(_CLASS.$this->channel);
}否则{
\Yii::warning('Queue->release()未等待锁');
}
}
}
/**
*将过期邮件移动到等待列表中。
*/
私有函数moveExpired()
{
如果($this->reserveTime!==time()){
$this->reserveTime=time();
$this->db->createCommand()->更新(
$this->tableName,
['reserved_at'=>null],
“[[reserved_at]]<:time-[[ttr]]和[[reserved_at]]不为空,[[done_at]]为空”,
[':time'=>$this->reserveTime]
)->执行();
}
}

谢谢你的建议。我们一直在测试解决方案。我们删除了mutexTimeout参数,并将其设置为3,但在这两种情况下都会不时出现错误。错误似乎与导出函数无关,因为错误是以“随机”方式发生的。我们将进一步调查,看看是否找到解决方案。欢迎提出任何其他想法。:)如果您有许多排队作业,DB queue可能会非常慢(至少在我的例子中MySQL上是慢的)——如果您有多个工作线程在繁忙的队列上,可能会导致这样的错误。另外,
PgsqlMutex
还远远不够完美,因为它并不真正等待锁,它只是多次重试,直到达到超时-如果您运气不好,每次尝试都可能失败,即使有时间帧,是否可以获得锁。您可以试试MysqlMutex,它在这方面应该更可靠。
'mutexTimeout' => 0,
/**
 * @param array $payload
 */
protected function release($payload)
{
    $mutex = $this->mutex->acquire(__CLASS__ . $this->channel, $this->mutexTimeout);

    try {
        if ($this->deleteReleased) {
            $this->db->createCommand()->delete(
                $this->tableName,
                ['id' => $payload['id']]
            )->execute();
        } else {
            $this->db->createCommand()->update(
                $this->tableName,
                ['done_at' => time()],
                ['id' => $payload['id']]
            )->execute();
        }
    } catch (Exception $e) {
        \Yii::error($e->getMessage());
    } finally {
        if ($mutex) {
            $this->mutex->release(__CLASS__ . $this->channel);
        } else {
            \Yii::warning('Queue->release() Has not waited the lock');
        }
    }
}

/**
 * Moves expired messages into waiting list.
 */
private function moveExpired()
{
    if ($this->reserveTime !== time()) {
        $this->reserveTime = time();
        $this->db->createCommand()->update(
            $this->tableName,
            ['reserved_at' => null],
            '[[reserved_at]] < :time - [[ttr]] and [[reserved_at]] is not null and [[done_at]] is null',
            [':time' => $this->reserveTime]
        )->execute();
    }
}