直播中
---- ODBC 2.0 访 问 数 据 库 时 存 在 同 步 与 异 步 执 行 模 式 之 分, 如 果 设 计 不 当, 则 易 发 生 系 统 故 障 甚 至 系 统 死 锁。 下 面 笔 者 就 实 践 经 验, 针 对ODBC 2.0 的 同 步 与 异 步 执 行 模 式 谈 一 点 使 用 经 验 和 设 置 方 法, 欲 与 同 行 们 商 榷。
---- 众 所 周 知, 应 用 程 序 要 从 一 个 大 表 中 删 除 所 有 的 记 录 将 是 非 常 耗 时 的, 如 果 应 用 程 序 采 用 的 是 单 线 程(thread) 同 步 执 行 方 式, 某 次 删 除 工 作 很 可 能 耽 误 其 他 重 要 工 作 的 完 成。 如 果 应 用 程 序 等 待 的 是 远 程 任 务, 那 么 远 程 服 务 器 失 败 或 网 络 故 障 或 一 些 无 法 预 知 的 情 况 都 可 能 使 应 用 程 序 无 限 期 地 等 下 去, 这 是 同 步 执 行 最 大 的 缺 陷。
---- 但 是 同 步 执 行 模 式 可 以 简 化 程 序 编 制 的 复 杂 性。 程 序 员 可 以 不 用 过 多 地 了 解 比 较 复 杂 的ODBC 2.0 API 的 使 用, 而 只 需 使 用ODBC 的 同 步 执 行 模 式 或 使 用 数 据 控 制 项 和 数 据 库 对 象 变 量 来 编 写 应 用 程 序, 可 以 提 高 开 发 效 率, 但 程 序 运 行 速 度 比 不 上 异 步 执 行 模 式 的 速 度。
---- 异 步 执 行 方 式 使 应 用 程 序 能 摆 脱 单 个 任 务 的 牵 制, 提 高 了 灵 活 性 和 应 用 程 序 的 执 行 效 率。 但 异 步 执 行 模 式 也 存 在 一 些 问 题, 如 它 增 加 了 编 程 的 复 杂 性, 特 别 是 编 写 互 用 性(interoperable) 要 求 较 高 的 程 序。
---- 在 负 荷 很 重 的 客 户 / 服 务 器 系 统 中, 适 宜 采 用 异 步 执 行 模 式。 在 这 种 环 境 下, 时 间 延 迟 频 繁 且 漫 长, 相 比 之 下 异 步 执 行 的 开 销 微 不 足 道。 但 是, 如 果 应 用 运 行 的 环 境 比 较 复 杂, 则 必 须 建 立 一 套 完 整 的 机 制, 周 期 性 地 检 查 函 数 执 行 的 状 态, 以 决 定 下 一 步 执 行 方 案。 进 行 周 期 的 检 查 可 以 有 多 种 方 法, 如 在 应 用 中 设 置 计 时 器 并 处 理WM_TIMER 信 息 等。
---- 虽 然 使 用 异 步 执 行 模 式 在 编 程 序 时 十 分 复 杂, 但 可 以 实 现 多 任 务 并 行 执 行, 使 执 行 的 效 率 大 大 提 高。
---- 对 于 一 般 程 序 员 来 说, 如 果 他 对 同 步 执 行 模 式 与 异 步 执 行 模 式 不 了 解, 他 往 往 会 在 对 服 务 器 发 出 一 个 操 作 语 句( 查 询 或 读 取 一 条 记 录 等 操 作) 后, 立 该 引 用 服 务 器 返 回 的 执 行 结 果, 或 者 对 该 结 果 进 行 下 一 步 操 作, 这 是 很 危 险 的。 因 为, 在 异 步 执 行 模 式 下, 客 户 机 上 的 后 续 语 句 是 在 该 操 作 语 句 发 出 后 接 着 执 行 的, 但 由 于 各 种 原 因, 服 务 器 不 一 定 能 执 行 完 该 操 作 语 句, 并 在 后 续 语 句 执 行 前 将 结 果 返 回 客 户 机。 因 此, 后 续 语 句 在 引 用 前 一 操 作 语 句 的 执 行 结 果 时, 往 往 会 因 为 该 执 行 结 果 并 不 存 在 而 引 用 了 错 误 的 值, 造 成 系 统 错 误 或 死 锁, 所 以 在 实 际 应 用 中 应 根 据 具 体 情 况 慎 重 选 择 执 行 模 式。
---- 在ODBC 2.0 API 中, 并 非 所 有 的 驱 动 程 度 都 支 持 异 步 执 行 方 式, 详 细 的 情 况 请 参 见 有 关 文 档。 但 如 果 编 写 的 是 互 操 作 性 要 求 较 高 的 应 用 程 序, 则 必 须 在 程 序 运 行 时 动 态 地 了 解 有 关 特 性。 了 解 一 个 函 数 是 否 支 持 异 步 执 行 模 式 的 具 体 方 法 很 简 单: 分 配 一 个 语 句 按 异 步 方 式 执 行 一 次, 若 能 成 功, 则 具 有 异 步 执 行 功 能, 否 则 便 不 具 有。 在ODBC 2.0 API 中, 函 数SQLSetStmtOption() 的 功 能 是 设 置 异 步 或 异 步 执 行 模 式, 调 用 该 函 数 的 形 式 如 下:
---- retcode=SQLSetStmtOption(hstmt,SQL_ ASYNC_ ENABLE,1);
---- 其 中hstmt 是 一 语 句 句 柄, 常 数SQL_ASYNC_ENABLE 是 所 设 置 的 选 项, 参 数1 是 该 选 项 开 的 标 志(0 表 示 该 选 项 关)。 如 果 函 数 返 回SQL_SUCCESS, 则 表 示 驱 动 程 序 支 持 该 选 项, 并 且hstmt 现 已 被 设 置 为 异 步 执 行 方 式; 如 果 函 数 返 回SQL_ERROR 则 表 示 驱 动 程 序 不 支 持 异 步 执 行 方 式。ODBC 2.0 API 中 共 有20 多 个 函 数 支 持 异 步 执 行, 如 下 所 示。
SQLColAttributes() SQLColumnPrivileges() SQLColumns() SQLDescribeCol() SQLDescribeParam() SQLExecDirect() SQLExecute() SQLExtendedFetch() SQLFetch() SQLForeignKeys() SQLGetData() SQLGetTypeInfo() SQLMoreResults() SQLNumParams() SQLNumResultCols() SQLParamData() SQLPrepare() SQLPrimaryKeyS() SQLProcedureColumns()SQLProcedures() SQLPutData() SQLSetPos() SQLSpecialColumns() SQLStatistics() SQLTablePrivileges() SQLTables()
---- 这 些 函 数 第 一 次 调 用 后, 将 返 回 值SQL_STILL_EXE_CUTING, 这 时 应 用 程 序 将 继 续 执 行 后 续 语 句。 过 一 段 时 间 后, 应 该 再 次 调 用 原 函 数, 而 且 要 注 意: 实 参 数 应 传 入 与 第 一 次 调 用 时 相 同 的 语 句 句 柄, 其 他 参 数 也 应 一 样( 但 会 被 忽 略)。 如 果 函 数 返 回 值 为SQL_SUCCESS, 则 表 明 该 语 句 已 经 执 行 完 毕; 如 果 函 数 返 回SQL_STILL_EXECUTING, 则 表 明 该 语 句 仍 在 执 行 中。 下 面 我 们 用 一 个 简 单 的 例 子 来 说 明:
---- RetCode=SQLSetStmtoption(hStmt,SQL_ASYNC_ ENABLE,1)
---- ( 置 语 句 执 行 模 式 为 异 步 执 行 模 式)
---- RetCode=SQLExecDirect(hStmt,“select * from employees”,23)
---- ( 执 行 其 他 操 作)
---- … …
---- RetCode=SQLExecDirect(hStmt,“select * from employees”,23)
---- 下 面 判 断SQLExecDirect() 是 否 已 执 行 完 毕:
---- if (iRetCode= SQL_STILL_EXECUTING) then
---- … … 该 语 句 未 执 行 完, 继 续 执 行 其 他 操 作
---- else
---- if (iRetCode=SQL_SUCCESS) THEN
---- … … 该 语 句 已 执 行 完, 可 对 语 句 操 作 结 果 进 行 处 理
---- ENDIF
---- ENDIF
---- 综 上 所 述, 我 们 在 使 用ODBC 2.0 API 编 制 应 用 程 序 时, 应 根 据 自 身 情 况, 适 当 选 择 同 号 和 异 号 两 种 模 式, 以 便 提 高 程 序 运 行 的 可 靠 性 和 执 行 效 率。