-
Daogang Qu authored
When we start server with ps protocol and disabled binlog, executing DDL statement did not get a chance to call update_gtids_impl(...) to release its specified gtid, due to it miss to call ha_commit_trans(...) in trans_commit_stmt(...), since it is not active at that time; DDLs were using COM_STMT_PREPARE/COM_STMT_EXECUTE, so it also missed to call mysql_parse(...) to release its specified gtid. We fix the problem by moving the call to gtid_end_transaction(...) away from mysql_parse(....), into mysql_execute_command(...), since these DDLs with ps protocol are calling mysql_execute_command(...) by COM_STMT_EXECUTE and other normal transactions are calling mysql_execute_command(...) by mysql_parse(...). BUG#19774317 GTID_NEXT WITH EMPTY TRANSACTIONS DOES NOT WORK INSIDE STORED PROCEDURES Setting gtid_next inside a stored procedure and committing an empty transaction does not work. The root cause is that we failed to log the empty group to consume the GTID specified by setting gtid_next , due to the transaction owned gtid is cleared before calling gtid_end_transaction in mysql_parse(...). We also can fix the first problem by moving the call to gtid_end_transaction(...) away from mysql_parse(....), into mysql_execute_command(...), since committing the empty transaction with a specified GTID in stored procedure has a chance to call gtid_end_transaction(...) in mysql_execute_command(...) to log an empty group to consume the specified GTID. Bug#20343644 ASSERTION AT BINLOG.CC:1120 WHEN GTID_MODE=ON, GTID_NEXT='UUID:NUMBER' Bug#20444828 WL7592: ASSERT `THD->VARIABLES.GTID_NEXT.TYPE == GTID_GROUP' ON CREATE..SELECT Problem1: When gtid_mode is on, Start a transaction with a specified gtid, then create a table to cause an error, on commit we are hitting an assertion failure "thd->variables.gtid_next.type != UNDEFINED_GROUP". Problem2: When gtid_mode is on, set gtid_next with a specified gtid, then execute the statement 'CREATE..SELECT' to cause an error, on commit we are hitting the above assertion failure. The root cause is that we set gtid_next to undefined in gtid_post_statement_checks(...), which is called unconditionally after any statement in THD::cleanup_after_query(...). This means that gtid_next will be set to undefined for implicitly committing statements, even if the statement failed with an error before the implicit commit happened. Then, the transaction is still open and gtid_next is undefined. This is an invalid state, which triggers the assertion at commit time. The gtid_post_statement_checks(...) was introduced in BUG#16223835, the reason the function is needed is the following case: 1. SET GTID_NEXT='<GTID that is already included in gtid_executed>'; 2. BEGIN; 3. ... dml dml dml ... 4. COMMIT; Then, the commit on line 4 will not invoke update_gtids_impl because the GTID is already included in GTID_EXECUTED so the thread does not own the GTID. So then the call to set_undefined from gtid_post_statement_checks is really needed in this case. But this causes it to call set_undefined too often and causes the assertion reported in this bug. To fix the problem, we remove gtid_post_statement_checks, add a call to set_undefined() in Gtid_state::update_gtids_impl(...), and add a call to update_gtids_impl(...) in gtid_end_transaction(...), in case the transaction owned gtid is empty and the gtid_next type is GTID_GROUP.
Daogang Qu authoredWhen we start server with ps protocol and disabled binlog, executing DDL statement did not get a chance to call update_gtids_impl(...) to release its specified gtid, due to it miss to call ha_commit_trans(...) in trans_commit_stmt(...), since it is not active at that time; DDLs were using COM_STMT_PREPARE/COM_STMT_EXECUTE, so it also missed to call mysql_parse(...) to release its specified gtid. We fix the problem by moving the call to gtid_end_transaction(...) away from mysql_parse(....), into mysql_execute_command(...), since these DDLs with ps protocol are calling mysql_execute_command(...) by COM_STMT_EXECUTE and other normal transactions are calling mysql_execute_command(...) by mysql_parse(...). BUG#19774317 GTID_NEXT WITH EMPTY TRANSACTIONS DOES NOT WORK INSIDE STORED PROCEDURES Setting gtid_next inside a stored procedure and committing an empty transaction does not work. The root cause is that we failed to log the empty group to consume the GTID specified by setting gtid_next , due to the transaction owned gtid is cleared before calling gtid_end_transaction in mysql_parse(...). We also can fix the first problem by moving the call to gtid_end_transaction(...) away from mysql_parse(....), into mysql_execute_command(...), since committing the empty transaction with a specified GTID in stored procedure has a chance to call gtid_end_transaction(...) in mysql_execute_command(...) to log an empty group to consume the specified GTID. Bug#20343644 ASSERTION AT BINLOG.CC:1120 WHEN GTID_MODE=ON, GTID_NEXT='UUID:NUMBER' Bug#20444828 WL7592: ASSERT `THD->VARIABLES.GTID_NEXT.TYPE == GTID_GROUP' ON CREATE..SELECT Problem1: When gtid_mode is on, Start a transaction with a specified gtid, then create a table to cause an error, on commit we are hitting an assertion failure "thd->variables.gtid_next.type != UNDEFINED_GROUP". Problem2: When gtid_mode is on, set gtid_next with a specified gtid, then execute the statement 'CREATE..SELECT' to cause an error, on commit we are hitting the above assertion failure. The root cause is that we set gtid_next to undefined in gtid_post_statement_checks(...), which is called unconditionally after any statement in THD::cleanup_after_query(...). This means that gtid_next will be set to undefined for implicitly committing statements, even if the statement failed with an error before the implicit commit happened. Then, the transaction is still open and gtid_next is undefined. This is an invalid state, which triggers the assertion at commit time. The gtid_post_statement_checks(...) was introduced in BUG#16223835, the reason the function is needed is the following case: 1. SET GTID_NEXT='<GTID that is already included in gtid_executed>'; 2. BEGIN; 3. ... dml dml dml ... 4. COMMIT; Then, the commit on line 4 will not invoke update_gtids_impl because the GTID is already included in GTID_EXECUTED so the thread does not own the GTID. So then the call to set_undefined from gtid_post_statement_checks is really needed in this case. But this causes it to call set_undefined too often and causes the assertion reported in this bug. To fix the problem, we remove gtid_post_statement_checks, add a call to set_undefined() in Gtid_state::update_gtids_impl(...), and add a call to update_gtids_impl(...) in gtid_end_transaction(...), in case the transaction owned gtid is empty and the gtid_next type is GTID_GROUP.
Loading