phalcon读写分离在事务中的使用(非官方推荐)

在用phalcon框架开发了一段时间项目之后,才发现需要做数据库读写分离,这时候就有一个问题了。

由于开发的时候没有安照phalcon官方推荐方式写程序,这时候有个问题,就是在使用到事务的时候,当事务中写操作没有提交,就直接读取刚才生成数据的时候,就发生了问题,写没有提交自然就读不到。

这时候:采用强制读操作在写库中进行,这样就能解决问题。

保证所有model继承一个自定义的baseModel ,并且全部继承parant

public function initialize()
{
    parent::initialize();
}

baseModel需要进行两个方法的实现:


public function initialize()
{
    $this->setWriteConnectionService('db');
    $this->setReadConnectionService('dbRead');
}

//refresh需要重写下,否则有问题得不到未提交的数据
public function refresh()
{
    if ($this->getWriteConnection()->isUnderTransaction()) {
        $this->setReadConnectionService('db');
    }
    return parent::refresh();}

在services中DI注入db和dbRead两个服务,db主库(其实dbWrite也可以,但是为了保证$this->db的一些方法兼容继续使用),dbRead从库

//默认库(为了兼容现有$this->db->操作)
$di->setShared('db', function () use ($di, $configEnv) {
    $connection = new DbAdapter([
        "host" => $configEnv->database->host,
        "username" => $configEnv->database->username,
        "password" => $configEnv->database->password,
        "dbname" => $configEnv->database->dbname,
        "charset" => "utf8"
    ]);
    return $connection;
});

// 读(从)库
$di->setShared('dbRead', function () use ($di, $configEnv) {
    $connection = new DbAdapter([
        "host" => $configEnv->r_database->host,
        "username" => $configEnv->r_database->username,
        "password" => $configEnv->r_database->password,
        "dbname" => $configEnv->r_database->dbname,
        "charset" => "utf8"
    ]);
    return $connection;
});

通过以上步骤,基本完成读写分离,但是由于前期可能不是官方读写分离写法,尤其是用到事务的时候,事务包含过程过大的时候:
如果此时刚创建完一个数据,但是事务还没有提交,下方有某个方法中已经使用了find及findFrist方法,此时是肯定读不到数据的,
所有需要将这部分的读强制的置为在主(写)库中进行读,这样事务还未提交的数据就能被查到了。

做法如下:
1:

$order = \Phalcon\Di::getDefault()->getShared('db')->fetchOne("select * from order_freight where id={$order_id} limit 1");
数字结果,强制转对象:$order = (object)$order;

2:

此方法更优,对框架原生支持比较好


$history = new AddressHistory();
$history = $history->setReadConnectionService('db');
$obj = $history->findFirst([
   'conditions' => "address_id = ?1 and is_latest = 1",
   'bind' => [1 => 15794],
]);

上述为后期弥补做法,官方推荐事务写法如下:

<?php

use Phalcon\Mvc\Model\Transaction\Failed as TxFailed;
use Phalcon\Mvc\Model\Transaction\Manager as TxManager;

try {
    // Create a transaction manager
    $manager = new TxManager();

    // Request a transaction
    $transaction = $manager->get();

    $robot = new Robots();

    $robot->setTransaction($transaction);

    $robot->name       = 'WALL·E';
    $robot->created_at = date('Y-m-d');

    if ($robot->save() === false) {
        $transaction->rollback(
            'Cannot save robot'
        );
    }

    $robotPart = new RobotParts();

    $robotPart->setTransaction($transaction);

    $robotPart->robots_id = $robot->id;
    $robotPart->type      = 'head';

    if ($robotPart->save() === false) {
        $transaction->rollback(
            'Cannot save robot part'
        );
    }

    // Everything's gone fine, let's commit the transaction
    $transaction->commit();
} catch (TxFailed $e) {
    echo 'Failed, reason: ', $e->getMessage();
}

猜你喜欢

转载自blog.csdn.net/jiedao_liyk/article/details/80762749
今日推荐