mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
(pushing for Andrei)
Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack Once had been set the flag might later got reset inside of a stored routine execution stack. The reason was in that there was no check if a new statement started at time of resetting. The artifact affects most of binlogable DML queries. Notice, that multi-update is wrapped up within bug@27716 fix, multi-delete bug@29136. Fixed with saving parent's statement flag of whether the statement modified non-transactional table, and unioning (merging) the value with that was gained in mysql_execute_command. Resettling thd->no_trans_update members into thd->transaction.`member`; Asserting code; Effectively the following properties are held. 1. At the end of a substatement thd->transaction.stmt.modified_non_trans_table reflects the fact if such a table got modified by the substatement. That also respects THD::really_abort_on_warnin() requirements. 2. Eventually thd->transaction.stmt.modified_non_trans_table will be computed as the union of the values of all invoked sub-statements. That fixes this bug#27417; Computing of thd->transaction.all.modified_non_trans_table is refined to base to the stmt's value for all the case including insert .. select statement which before the patch had an extra issue bug@28960. Minor issues are covered with mysql_load, mysql_delete, and binloggin of insert in to temp_table select. The supplied test verifies limitely, mostly asserts. The ultimate testing is defered for bug@13270, bug@23333.
This commit is contained in:
@@ -420,6 +420,35 @@ typedef struct st_thd_trans
|
||||
bool no_2pc;
|
||||
/* storage engines that registered themselves for this transaction */
|
||||
handlerton *ht[MAX_HA];
|
||||
/*
|
||||
The purpose of this flag is to keep track of non-transactional
|
||||
tables that were modified in scope of:
|
||||
- transaction, when the variable is a member of
|
||||
THD::transaction.all
|
||||
- top-level statement or sub-statement, when the variable is a
|
||||
member of THD::transaction.stmt
|
||||
This member has the following life cycle:
|
||||
* stmt.modified_non_trans_table is used to keep track of
|
||||
modified non-transactional tables of top-level statements. At
|
||||
the end of the previous statement and at the beginning of the session,
|
||||
it is reset to FALSE. If such functions
|
||||
as mysql_insert, mysql_update, mysql_delete etc modify a
|
||||
non-transactional table, they set this flag to TRUE. At the
|
||||
end of the statement, the value of stmt.modified_non_trans_table
|
||||
is merged with all.modified_non_trans_table and gets reset.
|
||||
* all.modified_non_trans_table is reset at the end of transaction
|
||||
|
||||
* Since we do not have a dedicated context for execution of a
|
||||
sub-statement, to keep track of non-transactional changes in a
|
||||
sub-statement, we re-use stmt.modified_non_trans_table.
|
||||
At entrance into a sub-statement, a copy of the value of
|
||||
stmt.modified_non_trans_table (containing the changes of the
|
||||
outer statement) is saved on stack. Then
|
||||
stmt.modified_non_trans_table is reset to FALSE and the
|
||||
substatement is executed. Then the new value is merged with the
|
||||
saved value.
|
||||
*/
|
||||
bool modified_non_trans_table;
|
||||
} THD_TRANS;
|
||||
|
||||
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
|
||||
|
||||
Reference in New Issue
Block a user