文档首页
MySQL NDB Cluster API 开发者指南
相关文档 下载本手册
PDF (US Ltr) - 3.6Mb
PDF (A4) - 3.6Mb


2.4.1 处理 NDB API 错误

摘要

本节介绍如何检测 NDB API 错误并将它们映射到特定操作。

NDB API 错误可以通过以下两种方式生成

  • 在定义操作时

  • 在执行操作时

在操作定义期间发生的错误。在操作定义期间生成的错误会导致调用的方法返回失败代码。可以通过检查相关的 NdbOperation 对象或操作的 NdbTransaction 对象来确定实际错误。

在操作执行期间发生的错误。在操作执行期间发生的错误会导致包含这些错误的事务被中止,除非为该操作设置了 AO_IgnoreError 中止选项。

默认情况下,读取操作以 AO_IgnoreError 运行,而写入操作以 AbortOnError 运行,但用户可以覆盖此设置。当执行期间发生的错误导致事务中止时,execute() 方法将返回失败代码。如果由于在操作上设置了 AO_IgnoreError 而忽略了错误,则 execute() 方法将返回成功代码,并且用户必须使用 NdbOperation::getNdbError() 检查所有操作是否失败。因此,即使 execute() 返回成功,也应该通常检查 getNdbError() 的返回值。如果客户端应用程序在执行期间没有跟踪 NdbOperation 对象,则可以使用 NdbTransaction::getNextCompletedOperation() 来迭代它们。

您还应该注意,使用 NdbBlob 会导致在执行的批次中添加额外的操作。这意味着,当使用 getNextCompletedOperation() 迭代已完成的操作时,您可能会遇到与您的应用程序未定义的 NdbBlob 对象相关的操作。

注意

LockModeCommittedRead 的读取不能为 AbortOnError。在这种情况下,它始终为 IgnoreError

在所有出现操作特定错误的情况下,都会在操作和相关事务对象上标记一个包含操作的执行错误。如果在单个 NdbTransaction::execute() 调用中存在多个操作错误,这是由于操作批处理和使用 AO_IgnoreError 造成的,则只会在 NdbTransaction 对象上标记第一个错误。其余错误只记录在相应的 NdbOperation 对象上。

在执行期间,还可能发生错误,例如数据节点故障,这些错误会在事务对象上标记,但不会在底层操作对象上标记。这是因为这些错误适用于整个事务,而不适用于事务中的各个操作。

因此,应用程序应使用 NdbTransaction::getNdbError() 作为确定 NdbTransaction::execute() 调用是否失败的第一种方法。如果正在执行的操作批次包含设置了 AO_IgnoreError 中止选项的操作,则可能存在多个操作错误,应使用 NdbTransaction::getNextCompletedOperation() 迭代已完成的操作集,并为每个操作调用 NdbOperation::getNdbError()

扫描和 BLOB 方法中的隐式 NdbTransaction::execute() 调用。扫描操作与其他操作以相同的方式执行,并且在 NdbScanOperation::nextResult() 方法中也有隐式 execute() 调用。当 NdbScanOperation::nextResult() 指示失败(即,如果方法返回 -1)时,应检查事务对象是否有错误。 NdbScanOperation 也可能包含错误,但前提是错误不是操作特定的。

某些 blob 操作方法也有隐式内部 execute() 调用,因此在这些点可能会遇到操作执行失败。以下 NdbBlob 方法可以生成隐式 execute() 调用;这意味着它们也需要检查 NdbTransaction 对象是否有错误,方法是使用 NdbTransaction::getNdbError(),如果它们返回错误代码

  • setNull()

  • truncate()

  • readData()

  • writeData()

总结。通常,在调用以下任何方法时,都可能在执行期间发生错误(导致返回失败代码)

如果发生这种情况,则应调用 NdbTransaction::getNdbError() 方法来识别发生的第一个错误。当操作被批处理并且批次中存在 IgnoreError 操作时,事务中可能存在多个包含错误的操作。可以通过使用 NdbTransaction::getNextCompletedOperation() 迭代已完成的操作集,并为每个操作调用 NdbOperation::getNdbError() 来找到这些错误。

当在一批要执行的操作中,任何操作都设置了 IgnoreError 时,即使实际上发生了错误,只要这些错误没有导致事务中止,NdbTransaction::execute() 方法也会指示成功。要确定是否发生了任何被忽略的错误,应使用 NdbTransaction::getNdbError() 检查事务错误状态。 只有当此方法指示成功时,您才能确定没有发生错误。如果此方法返回错误代码,并且操作已批处理,则应遍历所有已完成的操作以查找所有具有被忽略错误的操作。

示例 (伪代码).  我们首先执行一个事务,该事务可能包含批处理操作以及 AO_IgnoreErrorAbortOnError 中止选项的混合。

int execResult= NdbTransaction.execute(args);
注意

有关 args 的数量和允许值,请参见 NdbTransaction::execute()

接下来,由于 AO_IgnoreError 操作上的错误不会影响 execResult(即 execute() 返回的值),因此我们检查事务是否存在错误

NdbError err= NdbTransaction.getNdbError();

if (err.code != 0)
{

非零的错误代码值意味着在事务上引发了错误。这可能是由于以下任何情况导致的

  • 事务范围内的错误,例如数据节点故障,导致事务中止

  • 单个操作特定的错误,例如约束冲突,导致事务中止

  • 单个操作特定的被忽略错误,例如未找到数据,未导致事务中止

  • 许多操作特定的被忽略错误中的第一个,例如批处理时未找到数据,未导致事务中止

  • 在中止操作错误(事务中止)之前,在批处理时出现多个操作特定的被忽略错误,例如未找到数据

   if (execResult != 0)
   {

事务已被中止。在这种情况下,处理错误的推荐策略是测试事务错误状态,并根据其值采取适当的措施

      switch (err.status)
      {
        case value1:
          //  statement block handling value1 ...
        case value2:
          //  statement block handling value2 ...
          //  (etc. ...)
        case valueN:
          //  statement block handling valueN ...
      }

由于事务已中止,通常需要遍历已完成的操作(如果有),并且仅在您希望出于报告目的这样做时才查找每个操作引发的错误。

   }
   else
   {

事务本身未中止,但必须存在一个或多个被忽略的错误。在这种情况下,您应该遍历操作以确定发生了什么情况,并相应地处理原因。

   }
}

要处理返回 -1NdbScanOperation::nextResult(),表示操作失败(省略操作成功的情况)

int nextrc= NdbScanOperation.nextResult(args);
注意

有关 args 的数量和允许值,请参见 NdbScanOperation::nextResult()

if (nextrc == -1)
{

首先,您应该检查 NdbScanOperation 对象是否存在任何错误

  NdbError err= NdbScanOperation.getNdbError();

  if (err.code == 0)
  {

在扫描操作中未发现错误;错误必须属于整个事务。

  }
    err= NdbTransaction.getNdbError();

现在,您可以根据错误状态处理错误

    switch (err.status)
    {
      case value1:
        //  statement block handling value1 ...
      case value2:
        //  statement block handling value2 ...
        //  (etc. ...)
      case valueN:
        //  statement block handling valueN ...
    }
}

有关 NDB API 错误分类和状态代码的信息,请参见 第 2.4.4 节,“NDB 错误分类”。虽然您不应在 NDB API 应用程序中依赖特定的错误代码或消息文本(因为错误代码和消息都可能随着时间的推移而发生变化),但检查错误代码和消息有助于确定特定故障的原因。有关这些内容的更多信息,请参见 第 2.4.2 节,“NDB 错误代码:按类型”。有关 NdbError 以及可以从 NdbError 对象中获取的信息类型的更多信息,请参见 第 2.3.15 节,“NdbError 结构”