【问题标题】:MySQL with ND connection failover with PhalconPHP/PDO使用 PhalconPHP/PDO 进行 ND 连接故障转移的 MySQL
【发布时间】:2016-01-07 14:26:49
【问题描述】:

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

我愿意在 PhalconPHP 中实现它。因为我有几个使用 Phalcon 和 Mysql-nd 的重要项目,所以在正确的地方做这件事对我来说真的很重要。

试图找到一些文档,但找不到任何可以开始的示例。试图找到 EventManager 方法,查看 Phalcon 文档 herehere,但找不到透明的方法。

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

1 更新

在阅读了我发现的一些 Phalcon 资源后,可能无法以标准方式第二次运行相同的查询 - 我的意思是通过某种 PDO 参数或使用 Phalcons 的 EventManager 附加到 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);
    }

【问题讨论】:

    标签: php mysql pdo phalcon mysqlnd


    【解决方案1】:

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

    {
        "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);
    });
    

    即使它现在可以工作(当从属设备无法访问时,它最多会挂起 1 秒 - 这仍然是很多时间),它仍然不允许我从 PHP 源连接到编写recommended solution

    更新

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

    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 服务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-23
      • 2012-03-19
      • 2011-11-15
      • 2018-10-20
      • 2020-08-07
      • 1970-01-01
      • 2013-01-25
      • 2015-08-19
      相关资源
      最近更新 更多