Skip to content
  • Daogang Qu's avatar
    c627690b
    Bug#21895421 DEBUG ASSERT AFTER 'SET GTID_MODE' DURING PRECOMMIT OF GTID-VIOLATING STATEMENT · c627690b
    Daogang Qu authored
    Problem:
    
    A DBUG assert failure happened when changing GTID_MODE to
    ON/ON_PERMISSIVE and/or ENFORCE_GTID_CONSISTENCY to ON
    from OFF right after the ongoing GTID-violating statement
    causes to implicitly commit the previous transaction.
    
    Analysis:
    
    Some statements violate GTID consistency and therefore cannot be
    logged using GTIDs. Therefore, such statements are disallowed in
    the following cases: C1. enforce_gtid_consistency=ON, or C2.
    GTID_MODE=ON/ON_PERMISSIVE and GTID_NEXT=AUTOMATIC, or C3.
    GTID_NEXT=UUID:NUMBER. ENFORCE_GTID_CONSISTENCY and GTID_MODE are
    dynamic, but cannot be set to values that would make GTID-violating
    statements invalid in case there are ongoing GTID-violating
    statements. Therefore, to keep track of ongoing GTID-violating
    statements we maintain global counters of ongoing GTID-violating
    statements. A GTID-violating statement has three possible side
    effects: S1. generate an error (in case any of C1-C3 applies) S2.
    generate a warning (in case none of C1-C3 applies and
    enforce_gtid_consistency=WARN) S3. increase the GTID-violation
    counter (in case none of C1-C3 applies) If a GTID-violating
    statement has an implicit pre-commit, it was implemented such
    that S1 is done before the pre-commit and S2+S3 are done after
    the implicit pre-commit. The reason for this is: - S1 is before
    the pre-commit because it prevents the pre-commit from happening
    at all. - S3 is after the pre-commit because the counter is
    decremented on commit, and therefore if the counter was incremented
    before the implicit pre-commit, it would be immediately decremented,
    so the counter would not be effective for the duration of the
    statement. However, this opens up a race condition. After the
    GTID-consistency check for S1 has passed, and before the check for
    S2+S3 is done, it is possible to change GTID_MODE and/or
    ENFORCE_GTID_CONSISTENCY so that the check does not pass. That
    means the statement will execute, even if it is supposed to
    generate an error. This causes a debug assertion.
    
    Fix:
    
    It is fine that the error in S1 does not prevent the implicit
    pre-commit from happening, since users expect GTID-violating
    DDL statement to implicitly commit the previous transaction
    before executing it and we did the same thing in S2 and S3.
    All the logic (S1+S2+S3) can be moved until after the
    implicit pre-commit.
    c627690b
    Bug#21895421 DEBUG ASSERT AFTER 'SET GTID_MODE' DURING PRECOMMIT OF GTID-VIOLATING STATEMENT
    Daogang Qu authored
    Problem:
    
    A DBUG assert failure happened when changing GTID_MODE to
    ON/ON_PERMISSIVE and/or ENFORCE_GTID_CONSISTENCY to ON
    from OFF right after the ongoing GTID-violating statement
    causes to implicitly commit the previous transaction.
    
    Analysis:
    
    Some statements violate GTID consistency and therefore cannot be
    logged using GTIDs. Therefore, such statements are disallowed in
    the following cases: C1. enforce_gtid_consistency=ON, or C2.
    GTID_MODE=ON/ON_PERMISSIVE and GTID_NEXT=AUTOMATIC, or C3.
    GTID_NEXT=UUID:NUMBER. ENFORCE_GTID_CONSISTENCY and GTID_MODE are
    dynamic, but cannot be set to values that would make GTID-violating
    statements invalid in case there are ongoing GTID-violating
    statements. Therefore, to keep track of ongoing GTID-violating
    statements we maintain global counters of ongoing GTID-violating
    statements. A GTID-violating statement has three possible side
    effects: S1. generate an error (in case any of C1-C3 applies) S2.
    generate a warning (in case none of C1-C3 applies and
    enforce_gtid_consistency=WARN) S3. increase the GTID-violation
    counter (in case none of C1-C3 applies) If a GTID-violating
    statement has an implicit pre-commit, it was implemented such
    that S1 is done before the pre-commit and S2+S3 are done after
    the implicit pre-commit. The reason for this is: - S1 is before
    the pre-commit because it prevents the pre-commit from happening
    at all. - S3 is after the pre-commit because the counter is
    decremented on commit, and therefore if the counter was incremented
    before the implicit pre-commit, it would be immediately decremented,
    so the counter would not be effective for the duration of the
    statement. However, this opens up a race condition. After the
    GTID-consistency check for S1 has passed, and before the check for
    S2+S3 is done, it is possible to change GTID_MODE and/or
    ENFORCE_GTID_CONSISTENCY so that the check does not pass. That
    means the statement will execute, even if it is supposed to
    generate an error. This causes a debug assertion.
    
    Fix:
    
    It is fine that the error in S1 does not prevent the implicit
    pre-commit from happening, since users expect GTID-violating
    DDL statement to implicitly commit the previous transaction
    before executing it and we did the same thing in S2 and S3.
    All the logic (S1+S2+S3) can be moved until after the
    implicit pre-commit.
Loading