SQL事务能力

更新时间:
复制为 MD 格式

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;
  • 暂不支持DDLDML混合事务。

    如下示例,DDLDML在同一个事务中会报错: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;