Использование транзакций в CakePHP TreeBehavior? - PullRequest
0 голосов
/ 04 ноября 2019

Мы уже давно используем TreeBehavior с CakePHP 3.6. В последнее время с большим деревом (около 90000 узлов) мы сталкиваемся с проблемами.

При удалении узла функция beforeDelete () вызывается в cakephp / src / ORM / Behavior / TreeBehavior:

    /**
     * Also deletes the nodes in the subtree of the entity to be delete
     *
     * @param \Cake\Event\Event $event The beforeDelete event that was fired
     * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
     * @return void
     */
    public function beforeDelete(Event $event, EntityInterface $entity)
    {
        $config = $this->getConfig();
        $this->_ensureFields($entity);
        $left = $entity->get($config['left']);
        $right = $entity->get($config['right']);
        $diff = $right - $left + 1;
        if ($diff > 2) {
            $query = $this->_scope($this->_table->query())
                ->delete()
                ->where(function ($exp) use ($config, $left, $right) {
                    /* @var \Cake\Database\Expression\QueryExpression $exp */
                    return $exp
                        ->gte($config['leftField'], $left + 1)
                        ->lte($config['leftField'], $right - 1);
                });
            $statement = $query->execute();
            $statement->closeCursor();
        }
        $this->_sync($diff, '-', "> {$right}");
    }

Эта функция вызывает функцию _sync () для обновления левого и правого значений дерева:


    /**
     * Auxiliary function used to automatically alter the value of both the left and
     * right columns by a certain amount that match the passed conditions
     *
     * @param int $shift the value to use for operating the left and right columns
     * @param string $dir The operator to use for shifting the value (+/-)
     * @param string $conditions a SQL snipped to be used for comparing left or right
     * against it.
     * @param bool $mark whether to mark the updated values so that they can not be
     * modified by future calls to this function.
     * @return void
     */
    protected function _sync($shift, $dir, $conditions, $mark = false)
    {
        $config = $this->_config;
        foreach ([$config['leftField'], $config['rightField']] as $field) {
            $query = $this->_scope($this->_table->query());
            $exp = $query->newExpr();
            $movement = clone $exp;
            $movement->add($field)->add((string)$shift)->setConjunction($dir);
            $inverse = clone $exp;
            $movement = $mark ?
                $inverse->add($movement)->setConjunction('*')->add('-1') :
                $movement;
            $where = clone $exp;
            $where->add($field)->add($conditions)->setConjunction('');
            $query->update()
                ->set($exp->eq($field, $movement))
                ->where($where);
            $query->execute()->closeCursor();
        }
    }

Однако кажется, что запросы на обновление, выполняемые этой функцией _sync (), не являютсязаключены в транзакцию и выглядят следующим образом:

UPDATE `leafs` SET `lft` = ((`lft` - 12)) WHERE ((`lft`  > 52044))
UPDATE `leafs` SET `rght` = ((`rght` - 12)) WHERE ((`rght`  > 52044))

Разве они не должны быть заключены в транзакцию, как это?

START TRANSACTION
UPDATE `leafs` SET `lft` = ((`lft` - 12)) WHERE ((`lft`  > 52044))
UPDATE `leafs` SET `rght` = ((`rght` - 12)) WHERE ((`rght`  > 52044))
COMMIT

... особенно, если обновляются значения(левый и правый) также встречаются в предложении WHERE. У нас есть некоторые проблемы с повреждением дерева, и мы задаемся вопросом, может ли это быть причиной ... особенно, когда на большом дереве выполняется несколько последовательных операций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...