短错误

一些分布式的数据库群组使用短错误。一个短错误只是一段时间内的一个临时错误。 在一定的顶一下,这种忽略短错误并且重新在同一个数据库服务器中进行尝试是 安全的,尝试处理对客户端不产生影响。客户端将不会被迫终止他们的工作,或者去处理 另外一个数据库服务器的错误。他们将进入一个尝试处理错误的循环,而不需要等待错误 信息消失。例如,当使用 MySQL Cluster时,可以看到这种短错误信息。他们并不会被 绑定在特定的群组解决方案中。

插件可以提供在短错误中的自动尝试处理循环。这将提高分布处理的透明度,并且对于 应用程序从一个单独服务器运行一直到数据库服务群组执行变得更加简单。

自动的尝试循环,将不断的尝试,直到用户配置文件指定的次数,并且根据配置指定的 间隔时间进行短暂的等待。如果错误在循环过程中消失,应用程序将不会再看到这个 错误信息。如果错误没有消失,错误将被提交给应用程序进行处理。

下面的范例中,duplicate key 的错误内容在提交给应用程序以前,会被尝试处理 2 次, 两次尝试之间间隔 100 ms。

Example #1 Provoking a transient error

mysqlnd_ms.enable=1
mysqlnd_ms.collect_statistics=1
{
    "myapp": {
        "master": {
            "master_0": {
                "host": "localhost"
            }
        },
        "slave": {
            "slave_0": {
                "host": "192.168.78.136",
                "port": "3306"
            }
       },
       "transient_error": {
          "mysql_error_codes": [
            1062
          ],
          "max_retries": 2,
          "usleep_retry": 100
       }
    }
}

Example #2 短错误尝试循环

<?php
$mysqli 
= new mysqli("myapp""username""password""database");
if (
mysqli_connect_errno())
  
/* Of course, your error handling is nicer... */
  
die(sprintf("[%d] %s\n"mysqli_connect_errno(), mysqli_connect_error()));

if (!
$mysqli->query("DROP TABLE IF EXISTS test") ||
    !
$mysqli->query("CREATE TABLE test(id INT PRIMARY KEY)") ||
    !
$mysqli->query("INSERT INTO test(id) VALUES (1))")) {
  
printf("[%d] %s\n"$mysqli->errno$mysqli->error);
}

/* Retry loop is completely transparent. Checking statistics is
 the only way to know about implicit retries */
$stats mysqlnd_ms_get_stats();
printf("Transient error retries before error: %d\n"$stats['transient_error_retries']);

/* Provoking duplicate key error to see statistics change */
if (!$mysqli->query("INSERT INTO test(id) VALUES (1))")) {
  
printf("[%d] %s\n"$mysqli->errno$mysqli->error);
}

$stats mysqlnd_ms_get_stats();
printf("Transient error retries after error: %d\n"$stats['transient_error_retries']);

$mysqli->close();
?>

以上例程的输出类似于:

Transient error retries before error: 0
[1062] Duplicate entry '1' for key 'PRIMARY'
Transient error retries before error: 2

Because the execution of the retry loop is transparent from a users point of view, the example checks the statistics provided by the plugin to learn about it.

As the example shows, the plugin can be instructed to consider any error transient regardless of the database servers error semantics. The only error that a stock MySQL server considers temporary has the error code 1297. When configuring other error codes but 1297 make sure your configuration reflects the semantics of your clusters error codes.

The following mysqlnd C API calls are monitored by the plugin to check for transient errors: query(), change_user(), select_db(), set_charset(), set_server_option() prepare(), execute(), set_autocommit(), tx_begin(), tx_commit(), tx_rollback(), tx_commit_or_rollback(). The corresponding user API calls have similar names.

The maximum time the plugin may sleep during the retry loop depends on the function in question. The a retry loop for query(), prepare() or execute() will sleep for up to max_retries * usleep_retry milliseconds.

However, functions that control connection state are dispatched to all all connections. The retry loop settings are applied to every connection on which the command is to be run. Thus, such a function may interrupt program execution for longer than a function that is run on one server only. For example, set_autocommit() is dispatched to connections and may sleep up to (max_retries * usleep_retry) * number_of_open_connections) milliseconds. Please, keep this in mind when setting long sleep times and large retry numbers. Using the default settings of max_retries=1, usleep_retry=100 and lazy_connections=1 it is unlikely that you will ever see a delay of more than 1 second.