全部產品
Search
文件中心

Hologres:SQL事務能力

更新時間:Feb 28, 2026

Hologres支援完整的DDL事務以及部分DML事務,預設支援單條SQL事務。本文將會為您介紹Hologres的事務支援能力。

事務的支援情境

Hologres對事務的支援情境和使用說明如下:

  • 支援多條DDL語句事務

    事務內多個表的建立與復原支援事務保障,樣本如下:

    BEGIN;
    DROP TABLE IF EXISTS ddl_test;
    CREATE TABLE ddl_test(
              uid   TEXT NOT NULL,
              name  TEXT NOT NULL);
    COMMIT;
  • 支援多條DML混合事務(Beta)

    從 Hologres V2.0 版本開始支援同一個事務內的混合DML。通過混合DML事務的支援,可以保證同一個SQL中混合DML的原子性和一致性,尤其使資料寫入時能保證一致性,從而使得Hologres也適用輕TP的情境。但需要注意的是:一個事務中如果有混合DML,無法最大程度的利用Hologres的分布式能力,會使得混合DML無法支撐高QPS的情境。

    • 應用情境:混合DML在同一個事務中,可以保證資料寫入、更新、刪除的一致性。

    • 注意事項:

      • 混合DML事務只支援低QPS情境,不適用於高並發場合,具體QPS支援請進行實際業務測試。

      • 如果一個事務中,既有寫入又有查詢,查詢效能會低於不使用事務的情況,具體效能損失請以實際為準。

      • 同一個事務中,讀、寫、刪除、更新等請求均在表層級加寫鎖,會導致同一個表的多個事務只能串列執行,樣本如下。image

        重要

        需要注意的是,不僅是寫入的表會鎖表,查詢的也會鎖表,例如:

        • 使用者A執行如下SQL:

          SET hg_experimental_enable_transaction = on;
          BEGIN;
          DELETE FROM dml_test;
          INSERT INTO dml_test SELECT * FROM base_tbl;
          COMMIT;
        • 使用者B執行如下SQL:

          SET hg_experimental_enable_transaction = on;
          BEGIN;
          DELETE FROM dml_test_2;
          INSERT INTO dml_test_2 SELECT * FROM base_tbl;
          COMMIT;

        此時 base_tbl 也會鎖表,使用者B提交的SQL需要等待使用者A提交的SQL執行完畢,才會開始執行。所以開啟多行DML事務後,如果有衝突,SQL執行時間會明顯變長,甚至因為timeout的設定直接報錯。

    • 使用說明:

      目前混合DML事務預設關閉,需要通過如下GUC參數開啟:

      SET hg_experimental_enable_transaction = on;

      開啟混合DML事務後,在一個事務中可包含多個DML:

      • 如果其中一個DML失敗,那麼系統會自動將事務內的DML進行復原,其餘DML會自動失敗。

      • 如果DML正在正常執行中,因為某種原因想復原,可以對事務執行復原,這樣就會自動將事務中的DML復原。

        SET hg_experimental_enable_transaction = on;
        BEGIN;
        DELETE FROM dml_test;
        INSERT INTO dml_test VALUES (1,'sss');
        ROLLBACK;
  • 暫不支援DDL和DML混合事務。

    如下樣本,DDL和DML在同一個事務中會報錯:ERROR: INSERT in ddl transaction is not supported now

    BEGIN;
    DROP TABLE IF EXISTS dml_test;
    CREATE TABLE dml_test
    (
              uid   TEXT NOT NULL,
              name  TEXT NOT NULL);
    INSERT INTO dml_test VALUES('1','tom');
    COMMIT;