-
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.
Daogang Qu authoredProblem: 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