直播中
---- ODBC 2.0 訪 問 數(shù) 據(jù) 庫 時(shí) 存 在 同 步 與 異 步 執(zhí) 行 模 式 之 分, 如 果 設(shè) 計(jì) 不 當(dāng), 則 易 發(fā) 生 系 統(tǒng) 故 障 甚 至 系 統(tǒng) 死 鎖。 下 面 筆 者 就 實(shí) 踐 經(jīng) 驗(yàn), 針 對(duì)ODBC 2.0 的 同 步 與 異 步 執(zhí) 行 模 式 談 一 點(diǎn) 使 用 經(jīng) 驗(yàn) 和 設(shè) 置 方 法, 欲 與 同 行 們 商 榷。
---- 眾 所 周 知, 應(yīng) 用 程 序 要 從 一 個(gè) 大 表 中 刪 除 所 有 的 記 錄 將 是 非 常 耗 時(shí) 的, 如 果 應(yīng) 用 程 序 采 用 的 是 單 線 程(thread) 同 步 執(zhí) 行 方 式, 某 次 刪 除 工 作 很 可 能 耽 誤 其 他 重 要 工 作 的 完 成。 如 果 應(yīng) 用 程 序 等 待 的 是 遠(yuǎn) 程 任 務(wù), 那 么 遠(yuǎn) 程 服 務(wù) 器 失 敗 或 網(wǎng) 絡(luò) 故 障 或 一 些 無 法 預(yù) 知 的 情 況 都 可 能 使 應(yīng) 用 程 序 無 限 期 地 等 下 去, 這 是 同 步 執(zhí) 行 最 大 的 缺 陷。
---- 但 是 同 步 執(zhí) 行 模 式 可 以 簡 化 程 序 編 制 的 復(fù) 雜 性。 程 序 員 可 以 不 用 過 多 地 了 解 比 較 復(fù) 雜 的ODBC 2.0 API 的 使 用, 而 只 需 使 用ODBC 的 同 步 執(zhí) 行 模 式 或 使 用 數(shù) 據(jù) 控 制 項(xiàng) 和 數(shù) 據(jù) 庫 對(duì) 象 變 量 來 編 寫 應(yīng) 用 程 序, 可 以 提 高 開 發(fā) 效 率, 但 程 序 運(yùn) 行 速 度 比 不 上 異 步 執(zhí) 行 模 式 的 速 度。
---- 異 步 執(zhí) 行 方 式 使 應(yīng) 用 程 序 能 擺 脫 單 個(gè) 任 務(wù) 的 牽 制, 提 高 了 靈 活 性 和 應(yīng) 用 程 序 的 執(zhí) 行 效 率。 但 異 步 執(zhí) 行 模 式 也 存 在 一 些 問 題, 如 它 增 加 了 編 程 的 復(fù) 雜 性, 特 別 是 編 寫 互 用 性(interoperable) 要 求 較 高 的 程 序。
---- 在 負(fù) 荷 很 重 的 客 戶 / 服 務(wù) 器 系 統(tǒng) 中, 適 宜 采 用 異 步 執(zhí) 行 模 式。 在 這 種 環(huán) 境 下, 時(shí) 間 延 遲 頻 繁 且 漫 長, 相 比 之 下 異 步 執(zhí) 行 的 開 銷 微 不 足 道。 但 是, 如 果 應(yīng) 用 運(yùn) 行 的 環(huán) 境 比 較 復(fù) 雜, 則 必 須 建 立 一 套 完 整 的 機(jī) 制, 周 期 性 地 檢 查 函 數(shù) 執(zhí) 行 的 狀 態(tài), 以 決 定 下 一 步 執(zhí) 行 方 案。 進(jìn) 行 周 期 的 檢 查 可 以 有 多 種 方 法, 如 在 應(yīng) 用 中 設(shè) 置 計(jì) 時(shí) 器 并 處 理WM_TIMER 信 息 等。
---- 雖 然 使 用 異 步 執(zhí) 行 模 式 在 編 程 序 時(shí) 十 分 復(fù) 雜, 但 可 以 實(shí) 現(xiàn) 多 任 務(wù) 并 行 執(zhí) 行, 使 執(zhí) 行 的 效 率 大 大 提 高。
---- 對(duì) 于 一 般 程 序 員 來 說, 如 果 他 對(duì) 同 步 執(zhí) 行 模 式 與 異 步 執(zhí) 行 模 式 不 了 解, 他 往 往 會(huì) 在 對(duì) 服 務(wù) 器 發(fā) 出 一 個(gè) 操 作 語 句( 查 詢 或 讀 取 一 條 記 錄 等 操 作) 后, 立 該 引 用 服 務(wù) 器 返 回 的 執(zhí) 行 結(jié) 果, 或 者 對(duì) 該 結(jié) 果 進(jìn) 行 下 一 步 操 作, 這 是 很 危 險(xiǎn) 的。 因 為, 在 異 步 執(zhí) 行 模 式 下, 客 戶 機(jī) 上 的 后 續(xù) 語 句 是 在 該 操 作 語 句 發(fā) 出 后 接 著 執(zhí) 行 的, 但 由 于 各 種 原 因, 服 務(wù) 器 不 一 定 能 執(zhí) 行 完 該 操 作 語 句, 并 在 后 續(xù) 語 句 執(zhí) 行 前 將 結(jié) 果 返 回 客 戶 機(jī)。 因 此, 后 續(xù) 語 句 在 引 用 前 一 操 作 語 句 的 執(zhí) 行 結(jié) 果 時(shí), 往 往 會(huì) 因 為 該 執(zhí) 行 結(jié) 果 并 不 存 在 而 引 用 了 錯(cuò) 誤 的 值, 造 成 系 統(tǒng) 錯(cuò) 誤 或 死 鎖, 所 以 在 實(shí) 際 應(yīng) 用 中 應(yīng) 根 據(jù) 具 體 情 況 慎 重 選 擇 執(zhí) 行 模 式。
---- 在ODBC 2.0 API 中, 并 非 所 有 的 驅(qū) 動(dòng) 程 度 都 支 持 異 步 執(zhí) 行 方 式, 詳 細(xì) 的 情 況 請(qǐng) 參 見 有 關(guān) 文 檔。 但 如 果 編 寫 的 是 互 操 作 性 要 求 較 高 的 應(yīng) 用 程 序, 則 必 須 在 程 序 運(yùn) 行 時(shí) 動(dòng) 態(tài) 地 了 解 有 關(guān) 特 性。 了 解 一 個(gè) 函 數(shù) 是 否 支 持 異 步 執(zhí) 行 模 式 的 具 體 方 法 很 簡 單: 分 配 一 個(gè) 語 句 按 異 步 方 式 執(zhí) 行 一 次, 若 能 成 功, 則 具 有 異 步 執(zhí) 行 功 能, 否 則 便 不 具 有。 在ODBC 2.0 API 中, 函 數(shù)SQLSetStmtOption() 的 功 能 是 設(shè) 置 異 步 或 異 步 執(zhí) 行 模 式, 調(diào) 用 該 函 數(shù) 的 形 式 如 下:
---- retcode=SQLSetStmtOption(hstmt,SQL_ ASYNC_ ENABLE,1);
---- 其 中hstmt 是 一 語 句 句 柄, 常 數(shù)SQL_ASYNC_ENABLE 是 所 設(shè) 置 的 選 項(xiàng), 參 數(shù)1 是 該 選 項(xiàng) 開 的 標(biāo) 志(0 表 示 該 選 項(xiàng) 關(guān))。 如 果 函 數(shù) 返 回SQL_SUCCESS, 則 表 示 驅(qū) 動(dòng) 程 序 支 持 該 選 項(xiàng), 并 且hstmt 現(xiàn) 已 被 設(shè) 置 為 異 步 執(zhí) 行 方 式; 如 果 函 數(shù) 返 回SQL_ERROR 則 表 示 驅(qū) 動(dòng) 程 序 不 支 持 異 步 執(zhí) 行 方 式。ODBC 2.0 API 中 共 有20 多 個(gè) 函 數(shù) 支 持 異 步 執(zhí) 行, 如 下 所 示。
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()
---- 這 些 函 數(shù) 第 一 次 調(diào) 用 后, 將 返 回 值SQL_STILL_EXE_CUTING, 這 時(shí) 應(yīng) 用 程 序 將 繼 續(xù) 執(zhí) 行 后 續(xù) 語 句。 過 一 段 時(shí) 間 后, 應(yīng) 該 再 次 調(diào) 用 原 函 數(shù), 而 且 要 注 意: 實(shí) 參 數(shù) 應(yīng) 傳 入 與 第 一 次 調(diào) 用 時(shí) 相 同 的 語 句 句 柄, 其 他 參 數(shù) 也 應(yīng) 一 樣( 但 會(huì) 被 忽 略)。 如 果 函 數(shù) 返 回 值 為SQL_SUCCESS, 則 表 明 該 語 句 已 經(jīng) 執(zhí) 行 完 畢; 如 果 函 數(shù) 返 回SQL_STILL_EXECUTING, 則 表 明 該 語 句 仍 在 執(zhí) 行 中。 下 面 我 們 用 一 個(gè) 簡 單 的 例 子 來 說 明:
---- RetCode=SQLSetStmtoption(hStmt,SQL_ASYNC_ ENABLE,1)
---- ( 置 語 句 執(zhí) 行 模 式 為 異 步 執(zhí) 行 模 式)
---- RetCode=SQLExecDirect(hStmt,“select * from employees”,23)
---- ( 執(zhí) 行 其 他 操 作)
---- … …
---- RetCode=SQLExecDirect(hStmt,“select * from employees”,23)
---- 下 面 判 斷SQLExecDirect() 是 否 已 執(zhí) 行 完 畢:
---- if (iRetCode= SQL_STILL_EXECUTING) then
---- … … 該 語 句 未 執(zhí) 行 完, 繼 續(xù) 執(zhí) 行 其 他 操 作
---- else
---- if (iRetCode=SQL_SUCCESS) THEN
---- … … 該 語 句 已 執(zhí) 行 完, 可 對(duì) 語 句 操 作 結(jié) 果 進(jìn) 行 處 理
---- ENDIF
---- ENDIF
---- 綜 上 所 述, 我 們 在 使 用ODBC 2.0 API 編 制 應(yīng) 用 程 序 時(shí), 應(yīng) 根 據(jù) 自 身 情 況, 適 當(dāng) 選 擇 同 號(hào) 和 異 號(hào) 兩 種 模 式, 以 便 提 高 程 序 運(yùn) 行 的 可 靠 性 和 執(zhí) 行 效 率。