Mysql-nd手册的this部分描述了如何在失去与从MySQL服务器的连接时实现建议的故障转移方法。

我愿意在PhalconPHP中实现它。由于我有几个使用Phalcon和Mysql-nd的重要项目,因此在正确的位置完成它确实很重要。

试图找到一些文档,但是甚至找不到任何示例。正在尝试查找EventManager方法,调查了Phalcon文档herehere,但找不到透明地执行此操作的方法。

最吸引人的方法是使用event manager捕获错误事件并在连接错误时再次查询该事件。

1更新

阅读了一些我发现的Phalcon来源之后,可能无法以标准方式第二次运行相同的查询-我的意思是在这里通过某种PDO参数或使用附加到EventManager服务的Phalcons的db。我发现的一种可能的尝试是在db:afterConnection事件之后实际运行任何查询,但这不是解决方案。

2更新

db:afterConnection很难到达,相反可以在db:beforeQuery期间收集所有内容。问题是,PDO由Phalcon使用PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION运行,因此当与从属设备的连接死亡时,它将无法达到db:afterConnection事件。可以在db:beforeQuery期间获取PDO实例并通过EventManager更改此属性,但是它没有任何作用,因为即使我能够第二次发送相同的查询,也无法找到正确返回它的方法位置(在db:afterQuery期间不能覆盖查询结果)because obtained statement is not a part of event send, and Eventmanager result is not being used at all

    if typeof statement == "object" {
        if typeof eventsManager == "object" {
            eventsManager->fire("db:afterQuery", this, bindParams);
        }
        return new ResultPdo(this, statement, sqlStatement, bindParams, bindTypes);
    }

最佳答案

目前,它似乎已通过配置修复:

{
    "db-cluster": {
        "master": {
            "master": {
                "host": "master.local",
                "port": 3306
            }
        },
        "slave": {
            "slave-1": {
                "host": "slave-1.local",
                "port": 3306
            },
            "slave-2": {
                "host": "slave-2.local",
                "port": 3306
            },
            "slave-3": {
                "host": "slave-3.local",
                "port": 3306
            }
        },
        "filters": {
            "roundrobin": []
        },
        "failover": {
            "strategy": "loop_before_master",
            "remember_failed": true,
            "max_retries": 1
        },
        "server_charset": "utf8"
    }
}


如果服务器不可达,则会回退到其他服务器,问题是它试图连接到不可达服务器至少3秒钟。解决方法是:

$eventsManager = new EventsManager();
$connection->setEventsManager($eventsManager);

$eventsManager->attach('db:beforeQuery', function($event, $connection) {

    // fix: if slave does not respond, without this it goes over 3 seconds before trying next one
    !defined('DST') && define('DST', ini_get('default_socket_timeout'));
    ini_set("default_socket_timeout", 1);

});

$eventsManager->attach('db:afterQuery', function($event, $connection) {
    ini_set('default_socket_timeout', defined('DST') ? DST : 60);
});


即使它现在可以工作(当slave不可访问时,它最多挂在其上1秒钟-这仍然是很多时间),它仍然不允许我动手连接来自PHP源的代码以编写。

更新

通过扩展executePrepared类可以覆盖Phalcon\Db\Adapter\Pdo类中的Phalcon\Db\Adapter\Pdo\Mysql方法:

namespace Application;

use \PDOException;

class Mysql extends \Phalcon\Db\Adapter\Pdo\Mysql {

    public function executePrepared(statement, placeholders, dataTypes) {

        try {
            !defined('DST') && define('DST', ini_set('default_socket_timeout', 1));
            $stmt = parent::executePrepared(statement, placeholders, dataTypes);
            ini_set('default_socket_timeout', DST ?: 60);
            return $stmt;
        } catch(PDOException $e) {

            if(/* logic to find [2002, 2003, 2005] sql errors */) {
                return $this->executePrepared(statement, placeholders, dataTypes);
            }

            throw $e;
        }
    }
}


并使用它构建db服务。

关于php - 使用PhalconPHP/PDO进行ND连接故障转移的MySQL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34657598/

10-12 07:25