文字

错误处理

应用程序使用本插件,应该针对用户的 API 调用实现一些错误处理。并且由于插件 改变了连接控制,API 调用可能返回不可预期的错误。如果插件被用于连接控制中, 那么连接将不在代表一个独立的网络链接,他是一个连接池。那么一个错误编号和 错误消息将被设置在连接控制中,那么他可能被设置在任何一个实际的连接中。

如果使用默认的被动连接,那么连接再实际查询执行以前是不建立实际连接的。 这样一个执行语句的 API 调用会产生一个连接错误。下面的范例中,当尝试在 slave 中执行一个语句的时候将产生一个错误。连接错误的产生是因为在配置文件中 没有设定一个有效的 slave。

Example #1 Provoking a connection error

{
    "myapp": {
        "master": {
            "master_0": {
                "host": "localhost",
                "socket": "\/tmp\/mysql.sock"
            }
        },
        "slave": {
            "slave_0": {
                "host": "invalid_host_name",
            }
        },
        "lazy_connections": 1
    }
}

明确的指定被动连接设定只是为了范例目的使用。

Example #2 在查询执行时产生连接错误

<?php
$mysqli 
= new  mysqli ( "myapp" "username" "password" "database" );
if (
mysqli_connect_errno ())
  

  
die( sprintf ( "[%d] %s\n" mysqli_connect_errno (),  mysqli_connect_error ()));


if (! $mysqli -> query ( "SET @myrole='master'" )) {
 
printf ( "[%d] %s\n" $mysqli -> errno $mysqli -> error );
}


if (!( $res  $mysqli -> query ( "SELECT @myrole AS _role" ))) {
 
printf ( "[%d] %s\n" $mysqli -> errno $mysqli -> error );
} else {
 
$row  $res -> fetch_assoc ();
 
$res -> close ();
 
printf ( "@myrole = '%s'\n" $row [ '_role' ]);
}
$mysqli -> close ();
?>

以上例程的输出类似于:

PHP Warning:  mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d
PHP Warning:  mysqli::query(): [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known (trying to connect via tcp://invalid_host_name:3306) in %s on line %d
[2002] php_network_getaddresses: getaddrinfo failed: Name or service not known

应用程序希望通过有效的错误处理控制这种连接错误。

处于使用的目的,应用程序应该希望控制这些错误,典型的错误内容 2002 (CR_CONNECTION_ERROR) - Can't connect to local MySQL server through socket '%s' (%d), 2003 (CR_CONN_HOST_ERROR) - Can't connect to MySQL server on '%s' (%d)2005 (CR_UNKNOWN_HOST) - Unknown MySQL server host '%s' (%d)。 例如,应用程序可以判断这些错误编号,进而手动的执行某些错误处理。插件并不会自动的进行 这些错误处理,包括 master 错误处理,因为这些并不是透明的操作。

Example #3 产生一个连接错误

{
    "myapp": {
        "master": {
            "master_0": {
                "host": "localhost"
            }
        },
        "slave": {
            "slave_0": {
                "host": "invalid_host_name"
            },
            "slave_1": {
                "host": "192.168.78.136"
            }
        },
        "lazy_connections": 1,
        "filters": {
            "roundrobin": [            ]
        }
    }
}

明确的指定被动连接只为了进行范例使用,包括使用默认的负载均衡策略 random once

Example #4 非常基础的错误处理

<?php
$mysqli 
= new  mysqli ( "myapp" "username" "password" "database" );
if (
mysqli_connect_errno ())
  

  
die( sprintf ( "[%d] %s\n" mysqli_connect_errno (),  mysqli_connect_error ()));


if (! $mysqli -> query ( "SET @myrole='master'" )) {
 
printf ( "[%d] %s\n" $mysqli -> errno $mysqli -> error );
}


$res  $mysqli -> query ( "SELECT VERSION() AS _version" );

if ( 2002  ==  $mysqli -> errno  ||  2003  ==  $mysqli -> errno  ||  2004  ==  $mysqli -> errno ) {
  

  
$res  $mysqli -> query ( "SELECT VERSION() AS _version" );
}

if (!
$res ) {
  
printf ( "ERROR, [%d] '%s'\n" $mysqli -> errno $mysqli -> error );
} else {
 

 
printf ( "SUCCESS, [%d] '%s'\n" $mysqli -> errno $mysqli -> error );
 
$row  $res -> fetch_assoc ();
 
$res -> close ();
 
printf ( "version = %s\n" $row [ '_version' ]);
}
$mysqli -> close ();
?>

以上例程的输出类似于:

[1045] Access denied for user 'username'@'localhost' (using password: YES)
PHP Warning:  mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d
PHP Warning:  mysqli::query(): [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known (trying to connect via tcp://invalid_host_name:3306) in %s on line %d
SUCCESS, [0] ''
version = 5.6.2-m5-log

由于一些原因,连接控制并不可能很容易在所有网络连接中检查所有的错误。 例如,我们假设在连接池中有 3 个网络链接,一个连接是 master 连接,2个是 slave 链接。 应用程序通过 mysqli_select_db() API 调用改变当前操作数据库, 插件监控到这个函数,并且尝试更改当前的所有连接来统一他们的链接状态。如果 master 已经成功的更改了数据库,两个 slave 连接更改失败,那么在使用第一个 slave 连接的时候, 其中会包含一个连接错误。对于第二个 slave 链接也是一样的,那么在第一个 slave 上的 错误信息将被丢失。

这种情况下,可以通过检查 E_WARNING 类型的错误,或者检查 mysqlnd_ms debug and trace log。

上一篇: 下一篇: