You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3193 lines
80 KiB

10 years ago
11 years ago
12 years ago
12 years ago
12 years ago
12 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
12 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
11 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
12 years ago
12 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12219 Discard temporary undo logs at transaction commit Starting with MySQL 5.7, temporary tables in InnoDB are handled differently from persistent tables. Because temporary tables are private to a connection, concurrency control and multi-versioning (MVCC) are not applicable. For performance reasons, purge is disabled as well. Rollback is supported for temporary tables; that is why we have the temporary undo logs in the first place. Because MVCC and purge are disabled for temporary tables, we should discard all temporary undo logs already at transaction commit, just like we discard the persistent insert_undo logs. Before this change, update_undo logs were being preserved. trx_temp_undo_t: A wrapper for temporary undo logs, comprising a rollback segment and a single temporary undo log. trx_rsegs_t::m_noredo: Use trx_temp_undo_t. (Instead of insert_undo, update_undo, there will be a single undo.) trx_is_noredo_rseg_updated(), trx_is_rseg_assigned(): Remove. trx_undo_add_page(): Remove the parameter undo_ptr. Acquire and release the rollback segment mutex inside the function. trx_undo_free_last_page(): Remove the parameter trx. trx_undo_truncate_end(): Remove the parameter trx, and add the parameter is_temp. Clean up the code a bit. trx_undo_assign_undo(): Split the parameter undo_ptr into rseg, undo. trx_undo_commit_cleanup(): Renamed from trx_undo_insert_cleanup(). Replace the parameter undo_ptr with undo. This will discard the temporary undo or insert_undo log at commit/rollback. trx_purge_add_update_undo_to_history(), trx_undo_update_cleanup(): Remove 3 parameters. Always operate on the persistent update_undo. trx_serialise(): Renamed from trx_serialisation_number_get(). trx_write_serialisation_history(): Simplify the code flow. If there are no persistent changes, do not update MONITOR_TRX_COMMIT_UNDO. trx_commit_in_memory(): Simplify the logic, and add assertions. trx_undo_page_report_modify(): Keep a direct reference to the persistent update_undo log. trx_undo_report_row_operation(): Simplify some code. Always assign TRX_UNDO_INSERT for temporary undo logs. trx_prepare_low(): Keep only one parameter. Prepare all 3 undo logs. trx_roll_try_truncate(): Remove the parameter undo_ptr. Try to truncate all 3 undo logs of the transaction. trx_roll_pop_top_rec_of_trx_low(): Remove. trx_roll_pop_top_rec_of_trx(): Remove the redundant parameter trx->roll_limit. Clear roll_limit when exhausting the undo logs. Consider all 3 undo logs at once, prioritizing the persistent undo logs. row_undo(): Minor cleanup. Let trx_roll_pop_top_rec_of_trx() reset the trx->roll_limit.
9 years ago
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
9 years ago
  1. /*****************************************************************************
  2. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
  3. Copyright (c) 2015, 2017, MariaDB Corporation.
  4. This program is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free Software
  6. Foundation; version 2 of the License.
  7. This program is distributed in the hope that it will be useful, but WITHOUT
  8. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License along with
  11. this program; if not, write to the Free Software Foundation, Inc.,
  12. 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
  13. *****************************************************************************/
  14. /**************************************************//**
  15. @file trx/trx0trx.cc
  16. The transaction
  17. Created 3/26/1996 Heikki Tuuri
  18. *******************************************************/
  19. #include "ha_prototypes.h"
  20. #include "trx0trx.h"
  21. #ifdef WITH_WSREP
  22. #include <mysql/service_wsrep.h>
  23. #endif
  24. #include <mysql/service_thd_error_context.h>
  25. #include "btr0sea.h"
  26. #include "lock0lock.h"
  27. #include "log0log.h"
  28. #include "os0proc.h"
  29. #include "que0que.h"
  30. #include "read0read.h"
  31. #include "srv0mon.h"
  32. #include "srv0srv.h"
  33. #include "fsp0sysspace.h"
  34. #include "row0mysql.h"
  35. #include "srv0start.h"
  36. #include "trx0purge.h"
  37. #include "trx0rec.h"
  38. #include "trx0roll.h"
  39. #include "trx0rseg.h"
  40. #include "trx0undo.h"
  41. #include "trx0xa.h"
  42. #include "usr0sess.h"
  43. #include "ut0new.h"
  44. #include "ut0pool.h"
  45. #include "ut0vec.h"
  46. #include <set>
  47. #include <new>
  48. extern "C"
  49. int thd_deadlock_victim_preference(const MYSQL_THD thd1, const MYSQL_THD thd2);
  50. static const ulint MAX_DETAILED_ERROR_LEN = 256;
  51. /** Set of table_id */
  52. typedef std::set<
  53. table_id_t,
  54. std::less<table_id_t>,
  55. ut_allocator<table_id_t> > table_id_set;
  56. /** Dummy session used currently in MySQL interface */
  57. sess_t* trx_dummy_sess = NULL;
  58. /** Constructor */
  59. TrxVersion::TrxVersion(trx_t* trx)
  60. :
  61. m_trx(trx),
  62. m_version(trx->version)
  63. {
  64. /* No op */
  65. }
  66. /** Set flush observer for the transaction
  67. @param[in/out] trx transaction struct
  68. @param[in] observer flush observer */
  69. void
  70. trx_set_flush_observer(
  71. trx_t* trx,
  72. FlushObserver* observer)
  73. {
  74. trx->flush_observer = observer;
  75. }
  76. /*************************************************************//**
  77. Set detailed error message for the transaction. */
  78. void
  79. trx_set_detailed_error(
  80. /*===================*/
  81. trx_t* trx, /*!< in: transaction struct */
  82. const char* msg) /*!< in: detailed error message */
  83. {
  84. ut_strlcpy(trx->detailed_error, msg, MAX_DETAILED_ERROR_LEN);
  85. }
  86. /*************************************************************//**
  87. Set detailed error message for the transaction from a file. Note that the
  88. file is rewinded before reading from it. */
  89. void
  90. trx_set_detailed_error_from_file(
  91. /*=============================*/
  92. trx_t* trx, /*!< in: transaction struct */
  93. FILE* file) /*!< in: file to read message from */
  94. {
  95. os_file_read_string(file, trx->detailed_error, MAX_DETAILED_ERROR_LEN);
  96. }
  97. /********************************************************************//**
  98. Initialize transaction object.
  99. @param trx trx to initialize */
  100. static
  101. void
  102. trx_init(
  103. /*=====*/
  104. trx_t* trx)
  105. {
  106. /* This is called at the end of commit, do not reset the
  107. trx_t::state here to NOT_STARTED. The FORCED_ROLLBACK
  108. status is required for asynchronous handling. */
  109. trx->id = 0;
  110. trx->no = TRX_ID_MAX;
  111. trx->is_recovered = false;
  112. trx->op_info = "";
  113. trx->active_commit_ordered = 0;
  114. trx->isolation_level = TRX_ISO_REPEATABLE_READ;
  115. trx->check_foreigns = true;
  116. trx->check_unique_secondary = true;
  117. trx->lock.n_rec_locks = 0;
  118. trx->dict_operation = TRX_DICT_OP_NONE;
  119. trx->table_id = 0;
  120. trx->error_state = DB_SUCCESS;
  121. trx->error_key_num = ULINT_UNDEFINED;
  122. trx->undo_no = 0;
  123. trx->rsegs.m_redo.rseg = NULL;
  124. trx->rsegs.m_noredo.rseg = NULL;
  125. trx->read_only = false;
  126. trx->auto_commit = false;
  127. trx->will_lock = 0;
  128. trx->ddl = false;
  129. trx->internal = false;
  130. ut_d(trx->start_file = 0);
  131. ut_d(trx->start_line = 0);
  132. trx->magic_n = TRX_MAGIC_N;
  133. trx->lock.que_state = TRX_QUE_RUNNING;
  134. trx->last_sql_stat_start.least_undo_no = 0;
  135. ut_ad(!MVCC::is_view_active(trx->read_view));
  136. trx->lock.rec_cached = 0;
  137. trx->lock.table_cached = 0;
  138. /* During asynchronous rollback, we should reset forced rollback flag
  139. only after rollback is complete to avoid race with the thread owning
  140. the transaction. */
  141. if (!TrxInInnoDB::is_async_rollback(trx)) {
  142. my_atomic_storelong(&trx->killed_by, 0);
  143. /* Note: Do not set to 0, the ref count is decremented inside
  144. the TrxInInnoDB() destructor. We only need to clear the flags. */
  145. trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK;
  146. }
  147. /* Note: It's possible that this list is not empty if a transaction
  148. was interrupted after it collected the victim transactions and before
  149. it got a chance to roll them back asynchronously. */
  150. trx->hit_list.clear();
  151. trx->flush_observer = NULL;
  152. ++trx->version;
  153. }
  154. /** For managing the life-cycle of the trx_t instance that we get
  155. from the pool. */
  156. struct TrxFactory {
  157. /** Initializes a transaction object. It must be explicitly started
  158. with trx_start_if_not_started() before using it. The default isolation
  159. level is TRX_ISO_REPEATABLE_READ.
  160. @param trx Transaction instance to initialise */
  161. static void init(trx_t* trx)
  162. {
  163. /* Explicitly call the constructor of the already
  164. allocated object. trx_t objects are allocated by
  165. ut_zalloc() in Pool::Pool() which would not call
  166. the constructors of the trx_t members. */
  167. new(&trx->mod_tables) trx_mod_tables_t();
  168. new(&trx->lock.rec_pool) lock_pool_t();
  169. new(&trx->lock.table_pool) lock_pool_t();
  170. new(&trx->lock.table_locks) lock_pool_t();
  171. new(&trx->hit_list) hit_list_t();
  172. trx_init(trx);
  173. trx->state = TRX_STATE_NOT_STARTED;
  174. trx->dict_operation_lock_mode = 0;
  175. trx->xid = UT_NEW_NOKEY(xid_t());
  176. trx->detailed_error = reinterpret_cast<char*>(
  177. ut_zalloc_nokey(MAX_DETAILED_ERROR_LEN));
  178. trx->lock.lock_heap = mem_heap_create_typed(
  179. 1024, MEM_HEAP_FOR_LOCK_HEAP);
  180. lock_trx_lock_list_init(&trx->lock.trx_locks);
  181. UT_LIST_INIT(
  182. trx->trx_savepoints,
  183. &trx_named_savept_t::trx_savepoints);
  184. mutex_create(LATCH_ID_TRX, &trx->mutex);
  185. mutex_create(LATCH_ID_TRX_UNDO, &trx->undo_mutex);
  186. lock_trx_alloc_locks(trx);
  187. }
  188. /** Release resources held by the transaction object.
  189. @param trx the transaction for which to release resources */
  190. static void destroy(trx_t* trx)
  191. {
  192. ut_a(trx->magic_n == TRX_MAGIC_N);
  193. ut_ad(!trx->in_rw_trx_list);
  194. ut_ad(!trx->in_mysql_trx_list);
  195. ut_a(trx->lock.wait_lock == NULL);
  196. ut_a(trx->lock.wait_thr == NULL);
  197. trx_assert_no_search_latch(trx);
  198. ut_a(trx->dict_operation_lock_mode == 0);
  199. if (trx->lock.lock_heap != NULL) {
  200. mem_heap_free(trx->lock.lock_heap);
  201. trx->lock.lock_heap = NULL;
  202. }
  203. ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
  204. UT_DELETE(trx->xid);
  205. ut_free(trx->detailed_error);
  206. mutex_free(&trx->mutex);
  207. mutex_free(&trx->undo_mutex);
  208. trx->mod_tables.~trx_mod_tables_t();
  209. ut_ad(trx->read_view == NULL);
  210. if (!trx->lock.rec_pool.empty()) {
  211. /* See lock_trx_alloc_locks() why we only free
  212. the first element. */
  213. ut_free(trx->lock.rec_pool[0]);
  214. }
  215. if (!trx->lock.table_pool.empty()) {
  216. /* See lock_trx_alloc_locks() why we only free
  217. the first element. */
  218. ut_free(trx->lock.table_pool[0]);
  219. }
  220. trx->lock.rec_pool.~lock_pool_t();
  221. trx->lock.table_pool.~lock_pool_t();
  222. trx->lock.table_locks.~lock_pool_t();
  223. trx->hit_list.~hit_list_t();
  224. }
  225. /** Enforce any invariants here, this is called before the transaction
  226. is added to the pool.
  227. @return true if all OK */
  228. static bool debug(const trx_t* trx)
  229. {
  230. ut_a(trx->error_state == DB_SUCCESS);
  231. ut_a(trx->magic_n == TRX_MAGIC_N);
  232. ut_ad(!trx->read_only);
  233. ut_ad(trx->state == TRX_STATE_NOT_STARTED
  234. || trx->state == TRX_STATE_FORCED_ROLLBACK);
  235. ut_ad(trx->dict_operation == TRX_DICT_OP_NONE);
  236. ut_ad(trx->mysql_thd == 0);
  237. ut_ad(!trx->in_rw_trx_list);
  238. ut_ad(!trx->in_mysql_trx_list);
  239. ut_a(trx->lock.wait_thr == NULL);
  240. ut_a(trx->lock.wait_lock == NULL);
  241. trx_assert_no_search_latch(trx);
  242. ut_a(trx->dict_operation_lock_mode == 0);
  243. ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
  244. ut_ad(trx->autoinc_locks == NULL);
  245. ut_ad(trx->lock.table_locks.empty());
  246. ut_ad(!trx->abort);
  247. ut_ad(trx->hit_list.empty());
  248. ut_ad(trx->killed_by == 0);
  249. return(true);
  250. }
  251. };
  252. /** The lock strategy for TrxPool */
  253. struct TrxPoolLock {
  254. TrxPoolLock() { }
  255. /** Create the mutex */
  256. void create()
  257. {
  258. mutex_create(LATCH_ID_TRX_POOL, &m_mutex);
  259. }
  260. /** Acquire the mutex */
  261. void enter() { mutex_enter(&m_mutex); }
  262. /** Release the mutex */
  263. void exit() { mutex_exit(&m_mutex); }
  264. /** Free the mutex */
  265. void destroy() { mutex_free(&m_mutex); }
  266. /** Mutex to use */
  267. ib_mutex_t m_mutex;
  268. };
  269. /** The lock strategy for the TrxPoolManager */
  270. struct TrxPoolManagerLock {
  271. TrxPoolManagerLock() { }
  272. /** Create the mutex */
  273. void create()
  274. {
  275. mutex_create(LATCH_ID_TRX_POOL_MANAGER, &m_mutex);
  276. }
  277. /** Acquire the mutex */
  278. void enter() { mutex_enter(&m_mutex); }
  279. /** Release the mutex */
  280. void exit() { mutex_exit(&m_mutex); }
  281. /** Free the mutex */
  282. void destroy() { mutex_free(&m_mutex); }
  283. /** Mutex to use */
  284. ib_mutex_t m_mutex;
  285. };
  286. /** Use explicit mutexes for the trx_t pool and its manager. */
  287. typedef Pool<trx_t, TrxFactory, TrxPoolLock> trx_pool_t;
  288. typedef PoolManager<trx_pool_t, TrxPoolManagerLock > trx_pools_t;
  289. /** The trx_t pool manager */
  290. static trx_pools_t* trx_pools;
  291. /** Size of on trx_t pool in bytes. */
  292. static const ulint MAX_TRX_BLOCK_SIZE = 1024 * 1024 * 4;
  293. /** Create the trx_t pool */
  294. void
  295. trx_pool_init()
  296. {
  297. trx_pools = UT_NEW_NOKEY(trx_pools_t(MAX_TRX_BLOCK_SIZE));
  298. ut_a(trx_pools != 0);
  299. }
  300. /** Destroy the trx_t pool */
  301. void
  302. trx_pool_close()
  303. {
  304. UT_DELETE(trx_pools);
  305. trx_pools = 0;
  306. }
  307. /** @return a trx_t instance from trx_pools. */
  308. static
  309. trx_t*
  310. trx_create_low()
  311. {
  312. trx_t* trx = trx_pools->get();
  313. assert_trx_is_free(trx);
  314. mem_heap_t* heap;
  315. ib_alloc_t* alloc;
  316. /* We just got trx from pool, it should be non locking */
  317. ut_ad(trx->will_lock == 0);
  318. /* Background trx should not be forced to rollback,
  319. we will unset the flag for user trx. */
  320. trx->in_innodb |= TRX_FORCE_ROLLBACK_DISABLE;
  321. /* Trx state can be TRX_STATE_FORCED_ROLLBACK if
  322. the trx was forced to rollback before it's reused.*/
  323. trx->state = TRX_STATE_NOT_STARTED;
  324. heap = mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 8);
  325. alloc = ib_heap_allocator_create(heap);
  326. /* Remember to free the vector explicitly in trx_free(). */
  327. trx->autoinc_locks = ib_vector_create(alloc, sizeof(void**), 4);
  328. /* Should have been either just initialized or .clear()ed by
  329. trx_free(). */
  330. ut_a(trx->mod_tables.size() == 0);
  331. trx->vtq_notify_on_commit = false;
  332. #ifdef WITH_WSREP
  333. trx->wsrep_event = NULL;
  334. #endif /* WITH_WSREP */
  335. return(trx);
  336. }
  337. /**
  338. Release a trx_t instance back to the pool.
  339. @param trx the instance to release. */
  340. static
  341. void
  342. trx_free(trx_t*& trx)
  343. {
  344. assert_trx_is_free(trx);
  345. trx->mysql_thd = 0;
  346. trx->mysql_log_file_name = 0;
  347. // FIXME: We need to avoid this heap free/alloc for each commit.
  348. if (trx->autoinc_locks != NULL) {
  349. ut_ad(ib_vector_is_empty(trx->autoinc_locks));
  350. /* We allocated a dedicated heap for the vector. */
  351. ib_vector_free(trx->autoinc_locks);
  352. trx->autoinc_locks = NULL;
  353. }
  354. trx->mod_tables.clear();
  355. ut_ad(trx->read_view == NULL);
  356. /* trx locking state should have been reset before returning trx
  357. to pool */
  358. ut_ad(trx->will_lock == 0);
  359. trx_pools->mem_free(trx);
  360. trx = NULL;
  361. }
  362. /********************************************************************//**
  363. Creates a transaction object for background operations by the master thread.
  364. @return own: transaction object */
  365. trx_t*
  366. trx_allocate_for_background(void)
  367. /*=============================*/
  368. {
  369. trx_t* trx;
  370. trx = trx_create_low();
  371. trx->sess = trx_dummy_sess;
  372. return(trx);
  373. }
  374. /********************************************************************//**
  375. Creates a transaction object for MySQL.
  376. @return own: transaction object */
  377. trx_t*
  378. trx_allocate_for_mysql(void)
  379. /*========================*/
  380. {
  381. trx_t* trx;
  382. trx = trx_allocate_for_background();
  383. trx_sys_mutex_enter();
  384. ut_d(trx->in_mysql_trx_list = TRUE);
  385. UT_LIST_ADD_FIRST(trx_sys->mysql_trx_list, trx);
  386. trx_sys_mutex_exit();
  387. return(trx);
  388. }
  389. /** Check state of transaction before freeing it.
  390. @param trx trx object to validate */
  391. static
  392. void
  393. trx_validate_state_before_free(trx_t* trx)
  394. {
  395. if (trx->declared_to_be_inside_innodb) {
  396. ib::error() << "Freeing a trx (" << trx << ", "
  397. << trx_get_id_for_print(trx) << ") which is declared"
  398. " to be processing inside InnoDB";
  399. trx_print(stderr, trx, 600);
  400. putc('\n', stderr);
  401. /* This is an error but not a fatal error. We must keep
  402. the counters like srv_conc_n_threads accurate. */
  403. srv_conc_force_exit_innodb(trx);
  404. }
  405. if (trx->n_mysql_tables_in_use != 0
  406. || trx->mysql_n_tables_locked != 0) {
  407. ib::error() << "MySQL is freeing a thd though"
  408. " trx->n_mysql_tables_in_use is "
  409. << trx->n_mysql_tables_in_use
  410. << " and trx->mysql_n_tables_locked is "
  411. << trx->mysql_n_tables_locked << ".";
  412. trx_print(stderr, trx, 600);
  413. ut_print_buf(stderr, trx, sizeof(trx_t));
  414. putc('\n', stderr);
  415. }
  416. trx->dict_operation = TRX_DICT_OP_NONE;
  417. assert_trx_is_inactive(trx);
  418. }
  419. /** Free and initialize a transaction object instantinated during recovery.
  420. @param trx trx object to free and initialize during recovery */
  421. void
  422. trx_free_resurrected(trx_t* trx)
  423. {
  424. trx_validate_state_before_free(trx);
  425. trx_init(trx);
  426. trx_free(trx);
  427. }
  428. /** Free a transaction that was allocated by background or user threads.
  429. @param trx trx object to free */
  430. void
  431. trx_free_for_background(trx_t* trx)
  432. {
  433. trx_validate_state_before_free(trx);
  434. trx_free(trx);
  435. }
  436. /********************************************************************//**
  437. At shutdown, frees a transaction object that is in the PREPARED state. */
  438. void
  439. trx_free_prepared(
  440. /*==============*/
  441. trx_t* trx) /*!< in, own: trx object */
  442. {
  443. ut_a(trx_state_eq(trx, TRX_STATE_PREPARED)
  444. || (trx_state_eq(trx, TRX_STATE_ACTIVE)
  445. && trx->is_recovered
  446. && (!srv_was_started
  447. || srv_read_only_mode
  448. || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
  449. ut_a(trx->magic_n == TRX_MAGIC_N);
  450. lock_trx_release_locks(trx);
  451. trx_undo_free_prepared(trx);
  452. assert_trx_in_rw_list(trx);
  453. ut_a(!trx->read_only);
  454. ut_d(trx->in_rw_trx_list = FALSE);
  455. trx->state = TRX_STATE_NOT_STARTED;
  456. /* Undo trx_resurrect_table_locks(). */
  457. lock_trx_lock_list_init(&trx->lock.trx_locks);
  458. /* Note: This vector is not guaranteed to be empty because the
  459. transaction was never committed and therefore lock_trx_release()
  460. was not called. */
  461. trx->lock.table_locks.clear();
  462. trx_free(trx);
  463. }
  464. /** Disconnect a transaction from MySQL and optionally mark it as if
  465. it's been recovered. For the marking the transaction must be in prepared state.
  466. The recovery-marked transaction is going to survive "alone" so its association
  467. with the mysql handle is destroyed now rather than when it will be
  468. finally freed.
  469. @param[in,out] trx transaction
  470. @param[in] prepared boolean value to specify whether trx is
  471. for recovery or not. */
  472. inline
  473. void
  474. trx_disconnect_from_mysql(
  475. trx_t* trx,
  476. bool prepared)
  477. {
  478. trx_sys_mutex_enter();
  479. ut_ad(trx->in_mysql_trx_list);
  480. ut_d(trx->in_mysql_trx_list = FALSE);
  481. UT_LIST_REMOVE(trx_sys->mysql_trx_list, trx);
  482. if (trx->read_view != NULL) {
  483. trx_sys->mvcc->view_close(trx->read_view, true);
  484. }
  485. ut_ad(trx_sys_validate_trx_list());
  486. if (prepared) {
  487. ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
  488. trx->is_recovered = true;
  489. trx_sys->n_prepared_recovered_trx++;
  490. trx->mysql_thd = NULL;
  491. /* todo/fixme: suggest to do it at innodb prepare */
  492. trx->will_lock = 0;
  493. }
  494. trx_sys_mutex_exit();
  495. }
  496. /** Disconnect a transaction from MySQL.
  497. @param[in,out] trx transaction */
  498. inline
  499. void
  500. trx_disconnect_plain(trx_t* trx)
  501. {
  502. trx_disconnect_from_mysql(trx, false);
  503. }
  504. /** Disconnect a prepared transaction from MySQL.
  505. @param[in,out] trx transaction */
  506. void
  507. trx_disconnect_prepared(trx_t* trx)
  508. {
  509. trx_disconnect_from_mysql(trx, true);
  510. }
  511. /** Free a transaction object for MySQL.
  512. @param[in,out] trx transaction */
  513. void
  514. trx_free_for_mysql(trx_t* trx)
  515. {
  516. trx_disconnect_plain(trx);
  517. trx_free_for_background(trx);
  518. }
  519. /****************************************************************//**
  520. Resurrect the table locks for a resurrected transaction. */
  521. static
  522. void
  523. trx_resurrect_table_locks(
  524. /*======================*/
  525. trx_t* trx, /*!< in/out: transaction */
  526. const trx_undo_ptr_t* undo_ptr,
  527. /*!< in: pointer to undo segment. */
  528. const trx_undo_t* undo) /*!< in: undo log */
  529. {
  530. mtr_t mtr;
  531. page_t* undo_page;
  532. trx_undo_rec_t* undo_rec;
  533. table_id_set tables;
  534. ut_ad(undo == undo_ptr->insert_undo || undo == undo_ptr->update_undo);
  535. if (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) || undo->empty) {
  536. return;
  537. }
  538. mtr_start(&mtr);
  539. /* trx_rseg_mem_create() may have acquired an X-latch on this
  540. page, so we cannot acquire an S-latch. */
  541. undo_page = trx_undo_page_get(
  542. page_id_t(undo->space, undo->top_page_no), &mtr);
  543. undo_rec = undo_page + undo->top_offset;
  544. do {
  545. ulint type;
  546. undo_no_t undo_no;
  547. table_id_t table_id;
  548. ulint cmpl_info;
  549. bool updated_extern;
  550. page_t* undo_rec_page = page_align(undo_rec);
  551. if (undo_rec_page != undo_page) {
  552. mtr.release_page(undo_page, MTR_MEMO_PAGE_X_FIX);
  553. undo_page = undo_rec_page;
  554. }
  555. trx_undo_rec_get_pars(
  556. undo_rec, &type, &cmpl_info,
  557. &updated_extern, &undo_no, &table_id);
  558. tables.insert(table_id);
  559. undo_rec = trx_undo_get_prev_rec(
  560. undo_rec, undo->hdr_page_no,
  561. undo->hdr_offset, false, &mtr);
  562. } while (undo_rec);
  563. mtr_commit(&mtr);
  564. for (table_id_set::const_iterator i = tables.begin();
  565. i != tables.end(); i++) {
  566. if (dict_table_t* table = dict_table_open_on_id(
  567. *i, FALSE, DICT_TABLE_OP_LOAD_TABLESPACE)) {
  568. if (table->ibd_file_missing
  569. || dict_table_is_temporary(table)) {
  570. mutex_enter(&dict_sys->mutex);
  571. dict_table_close(table, TRUE, FALSE);
  572. dict_table_remove_from_cache(table);
  573. mutex_exit(&dict_sys->mutex);
  574. continue;
  575. }
  576. if (trx->state == TRX_STATE_PREPARED) {
  577. trx->mod_tables.insert(table);
  578. }
  579. lock_table_ix_resurrect(table, trx);
  580. DBUG_PRINT("ib_trx",
  581. ("resurrect" TRX_ID_FMT
  582. " table '%s' IX lock from %s undo",
  583. trx_get_id_for_print(trx),
  584. table->name.m_name,
  585. undo == undo_ptr->insert_undo
  586. ? "insert" : "update"));
  587. dict_table_close(table, FALSE, FALSE);
  588. }
  589. }
  590. }
  591. /****************************************************************//**
  592. Resurrect the transactions that were doing inserts the time of the
  593. crash, they need to be undone.
  594. @return trx_t instance */
  595. static
  596. trx_t*
  597. trx_resurrect_insert(
  598. /*=================*/
  599. trx_undo_t* undo, /*!< in: entry to UNDO */
  600. trx_rseg_t* rseg) /*!< in: rollback segment */
  601. {
  602. trx_t* trx;
  603. trx = trx_allocate_for_background();
  604. ut_d(trx->start_file = __FILE__);
  605. ut_d(trx->start_line = __LINE__);
  606. trx->rsegs.m_redo.rseg = rseg;
  607. /* For transactions with active data will not have rseg size = 1
  608. or will not qualify for purge limit criteria. So it is safe to increment
  609. this trx_ref_count w/o mutex protection. */
  610. ++trx->rsegs.m_redo.rseg->trx_ref_count;
  611. *trx->xid = undo->xid;
  612. trx->id = undo->trx_id;
  613. trx->rsegs.m_redo.insert_undo = undo;
  614. trx->is_recovered = true;
  615. /* This is single-threaded startup code, we do not need the
  616. protection of trx->mutex or trx_sys->mutex here. */
  617. if (undo->state != TRX_UNDO_ACTIVE) {
  618. /* Prepared transactions are left in the prepared state
  619. waiting for a commit or abort decision from MySQL */
  620. if (undo->state == TRX_UNDO_PREPARED) {
  621. ib::info() << "Transaction "
  622. << trx_get_id_for_print(trx)
  623. << " was in the XA prepared state.";
  624. if (srv_force_recovery == 0) {
  625. trx->state = TRX_STATE_PREPARED;
  626. ++trx_sys->n_prepared_trx;
  627. ++trx_sys->n_prepared_recovered_trx;
  628. } else {
  629. ib::info() << "Since innodb_force_recovery"
  630. " > 0, we will force a rollback.";
  631. trx->state = TRX_STATE_ACTIVE;
  632. }
  633. } else {
  634. trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
  635. }
  636. /* We give a dummy value for the trx no; this should have no
  637. relevance since purge is not interested in committed
  638. transaction numbers, unless they are in the history
  639. list, in which case it looks the number from the disk based
  640. undo log structure */
  641. trx->no = trx->id;
  642. } else {
  643. trx->state = TRX_STATE_ACTIVE;
  644. /* A running transaction always has the number
  645. field inited to TRX_ID_MAX */
  646. trx->no = TRX_ID_MAX;
  647. }
  648. /* trx_start_low() is not called with resurrect, so need to initialize
  649. start time here.*/
  650. if (trx->state == TRX_STATE_ACTIVE
  651. || trx->state == TRX_STATE_PREPARED) {
  652. trx->start_time = ut_time();
  653. }
  654. if (undo->dict_operation) {
  655. trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
  656. trx->table_id = undo->table_id;
  657. }
  658. if (!undo->empty) {
  659. trx->undo_no = undo->top_undo_no + 1;
  660. trx->undo_rseg_space = undo->rseg->space;
  661. }
  662. return(trx);
  663. }
  664. /****************************************************************//**
  665. Prepared transactions are left in the prepared state waiting for a
  666. commit or abort decision from MySQL */
  667. static
  668. void
  669. trx_resurrect_update_in_prepared_state(
  670. /*===================================*/
  671. trx_t* trx, /*!< in,out: transaction */
  672. const trx_undo_t* undo) /*!< in: update UNDO record */
  673. {
  674. /* This is single-threaded startup code, we do not need the
  675. protection of trx->mutex or trx_sys->mutex here. */
  676. if (undo->state == TRX_UNDO_PREPARED) {
  677. ib::info() << "Transaction " << trx_get_id_for_print(trx)
  678. << " was in the XA prepared state.";
  679. if (srv_force_recovery == 0) {
  680. ut_ad(trx->state != TRX_STATE_FORCED_ROLLBACK);
  681. if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {
  682. ++trx_sys->n_prepared_trx;
  683. ++trx_sys->n_prepared_recovered_trx;
  684. } else {
  685. ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
  686. }
  687. trx->state = TRX_STATE_PREPARED;
  688. } else {
  689. ib::info() << "Since innodb_force_recovery > 0, we"
  690. " will rollback it anyway.";
  691. trx->state = TRX_STATE_ACTIVE;
  692. }
  693. } else {
  694. trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
  695. }
  696. }
  697. /****************************************************************//**
  698. Resurrect the transactions that were doing updates the time of the
  699. crash, they need to be undone. */
  700. static
  701. void
  702. trx_resurrect_update(
  703. /*=================*/
  704. trx_t* trx, /*!< in/out: transaction */
  705. trx_undo_t* undo, /*!< in/out: update UNDO record */
  706. trx_rseg_t* rseg) /*!< in/out: rollback segment */
  707. {
  708. trx->rsegs.m_redo.rseg = rseg;
  709. /* For transactions with active data will not have rseg size = 1
  710. or will not qualify for purge limit criteria. So it is safe to increment
  711. this trx_ref_count w/o mutex protection. */
  712. ++trx->rsegs.m_redo.rseg->trx_ref_count;
  713. *trx->xid = undo->xid;
  714. trx->id = undo->trx_id;
  715. trx->rsegs.m_redo.update_undo = undo;
  716. trx->is_recovered = true;
  717. /* This is single-threaded startup code, we do not need the
  718. protection of trx->mutex or trx_sys->mutex here. */
  719. if (undo->state != TRX_UNDO_ACTIVE) {
  720. trx_resurrect_update_in_prepared_state(trx, undo);
  721. /* We give a dummy value for the trx number */
  722. trx->no = trx->id;
  723. } else {
  724. trx->state = TRX_STATE_ACTIVE;
  725. /* A running transaction always has the number field inited to
  726. TRX_ID_MAX */
  727. trx->no = TRX_ID_MAX;
  728. }
  729. /* trx_start_low() is not called with resurrect, so need to initialize
  730. start time here.*/
  731. if (trx->state == TRX_STATE_ACTIVE
  732. || trx->state == TRX_STATE_PREPARED) {
  733. trx->start_time = ut_time();
  734. }
  735. if (undo->dict_operation) {
  736. trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
  737. trx->table_id = undo->table_id;
  738. }
  739. if (!undo->empty && undo->top_undo_no >= trx->undo_no) {
  740. trx->undo_no = undo->top_undo_no + 1;
  741. trx->undo_rseg_space = undo->rseg->space;
  742. }
  743. }
  744. /** Initialize (resurrect) transactions at startup. */
  745. void
  746. trx_lists_init_at_db_start()
  747. {
  748. ut_a(srv_is_being_started);
  749. ut_ad(!srv_was_started);
  750. ut_ad(!purge_sys);
  751. purge_sys = UT_NEW_NOKEY(purge_sys_t());
  752. if (srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
  753. trx_rseg_array_init();
  754. }
  755. /* Look from the rollback segments if there exist undo logs for
  756. transactions. */
  757. for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
  758. trx_undo_t* undo;
  759. trx_rseg_t* rseg = trx_sys->rseg_array[i];
  760. /* At this stage non-redo rseg slots are all NULL as they are
  761. re-created on server start and existing slots are not read. */
  762. if (rseg == NULL) {
  763. continue;
  764. }
  765. /* Resurrect transactions that were doing inserts. */
  766. for (undo = UT_LIST_GET_FIRST(rseg->insert_undo_list);
  767. undo != NULL;
  768. undo = UT_LIST_GET_NEXT(undo_list, undo)) {
  769. trx_t* trx;
  770. trx = trx_resurrect_insert(undo, rseg);
  771. trx_sys_rw_trx_add(trx);
  772. trx_resurrect_table_locks(
  773. trx, &trx->rsegs.m_redo, undo);
  774. }
  775. /* Ressurrect transactions that were doing updates. */
  776. for (undo = UT_LIST_GET_FIRST(rseg->update_undo_list);
  777. undo != NULL;
  778. undo = UT_LIST_GET_NEXT(undo_list, undo)) {
  779. /* Check the trx_sys->rw_trx_set first. */
  780. trx_sys_mutex_enter();
  781. trx_t* trx = trx_get_rw_trx_by_id(undo->trx_id);
  782. trx_sys_mutex_exit();
  783. if (trx == NULL) {
  784. trx = trx_allocate_for_background();
  785. ut_d(trx->start_file = __FILE__);
  786. ut_d(trx->start_line = __LINE__);
  787. }
  788. trx_resurrect_update(trx, undo, rseg);
  789. trx_sys_rw_trx_add(trx);
  790. trx_resurrect_table_locks(
  791. trx, &trx->rsegs.m_redo, undo);
  792. }
  793. }
  794. TrxIdSet::iterator end = trx_sys->rw_trx_set.end();
  795. for (TrxIdSet::iterator it = trx_sys->rw_trx_set.begin();
  796. it != end;
  797. ++it) {
  798. ut_ad(it->m_trx->in_rw_trx_list);
  799. #ifdef UNIV_DEBUG
  800. if (it->m_trx->id > trx_sys->rw_max_trx_id) {
  801. trx_sys->rw_max_trx_id = it->m_trx->id;
  802. }
  803. #endif /* UNIV_DEBUG */
  804. if (it->m_trx->state == TRX_STATE_ACTIVE
  805. || it->m_trx->state == TRX_STATE_PREPARED) {
  806. trx_sys->rw_trx_ids.push_back(it->m_id);
  807. }
  808. UT_LIST_ADD_FIRST(trx_sys->rw_trx_list, it->m_trx);
  809. }
  810. }
  811. /** Assign a persistent rollback segment in a round-robin fashion,
  812. evenly distributed between 0 and innodb_undo_logs-1
  813. @return persistent rollback segment
  814. @retval NULL if innodb_read_only */
  815. static
  816. trx_rseg_t*
  817. trx_assign_rseg_low()
  818. {
  819. if (srv_read_only_mode) {
  820. ut_ad(srv_undo_logs == ULONG_UNDEFINED);
  821. return(NULL);
  822. }
  823. /* The first slot is always assigned to the system tablespace. */
  824. ut_ad(trx_sys->rseg_array[0]->space == TRX_SYS_SPACE);
  825. /* Choose a rollback segment evenly distributed between 0 and
  826. innodb_undo_logs-1 in a round-robin fashion, skipping those
  827. undo tablespaces that are scheduled for truncation.
  828. Because rseg_slot is not protected by atomics or any mutex, race
  829. conditions are possible, meaning that multiple transactions
  830. that start modifications concurrently will write their undo
  831. log to the same rollback segment. */
  832. static ulong rseg_slot;
  833. ulint slot = rseg_slot++ % srv_undo_logs;
  834. trx_rseg_t* rseg;
  835. #ifdef UNIV_DEBUG
  836. ulint start_scan_slot = slot;
  837. bool look_for_rollover = false;
  838. #endif /* UNIV_DEBUG */
  839. bool allocated = false;
  840. do {
  841. for (;;) {
  842. rseg = trx_sys->rseg_array[slot];
  843. #ifdef UNIV_DEBUG
  844. /* Ensure that we are not revisiting the same
  845. slot that we have already inspected. */
  846. if (look_for_rollover) {
  847. ut_ad(start_scan_slot != slot);
  848. }
  849. look_for_rollover = true;
  850. #endif /* UNIV_DEBUG */
  851. slot = (slot + 1) % srv_undo_logs;
  852. if (rseg == NULL) {
  853. continue;
  854. }
  855. ut_ad(rseg->is_persistent());
  856. if (rseg->space != TRX_SYS_SPACE) {
  857. ut_ad(srv_undo_tablespaces > 1);
  858. if (rseg->skip_allocation) {
  859. continue;
  860. }
  861. } else if (trx_rseg_t* next
  862. = trx_sys->rseg_array[slot]) {
  863. if (next->space != TRX_SYS_SPACE
  864. && srv_undo_tablespaces > 0) {
  865. /** If dedicated
  866. innodb_undo_tablespaces have
  867. been configured, try to use them
  868. instead of the system tablespace. */
  869. continue;
  870. }
  871. }
  872. break;
  873. }
  874. /* By now we have only selected the rseg but not marked it
  875. allocated. By marking it allocated we are ensuring that it will
  876. never be selected for UNDO truncate purge. */
  877. mutex_enter(&rseg->mutex);
  878. if (!rseg->skip_allocation) {
  879. rseg->trx_ref_count++;
  880. allocated = true;
  881. }
  882. mutex_exit(&rseg->mutex);
  883. } while (!allocated);
  884. ut_ad(rseg->trx_ref_count > 0);
  885. ut_ad(rseg->is_persistent());
  886. return(rseg);
  887. }
  888. /** Assign a rollback segment for modifying temporary tables.
  889. @return the assigned rollback segment */
  890. trx_rseg_t*
  891. trx_t::assign_temp_rseg()
  892. {
  893. ut_ad(!rsegs.m_noredo.rseg);
  894. ut_ad(!trx_is_autocommit_non_locking(this));
  895. compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS));
  896. /* Choose a temporary rollback segment between 0 and 127
  897. in a round-robin fashion. Because rseg_slot is not protected by
  898. atomics or any mutex, race conditions are possible, meaning that
  899. multiple transactions that start modifications concurrently
  900. will write their undo log to the same rollback segment. */
  901. static ulong rseg_slot;
  902. trx_rseg_t* rseg = trx_sys->temp_rsegs[
  903. rseg_slot++ & (TRX_SYS_N_RSEGS - 1)];
  904. ut_ad(!rseg->is_persistent());
  905. rsegs.m_noredo.rseg = rseg;
  906. if (id == 0) {
  907. mutex_enter(&trx_sys->mutex);
  908. id = trx_sys_get_new_trx_id();
  909. trx_sys->rw_trx_ids.push_back(id);
  910. trx_sys->rw_trx_set.insert(TrxTrack(id, this));
  911. mutex_exit(&trx_sys->mutex);
  912. }
  913. ut_ad(!rseg->is_persistent());
  914. return(rseg);
  915. }
  916. /****************************************************************//**
  917. Starts a transaction. */
  918. static
  919. void
  920. trx_start_low(
  921. /*==========*/
  922. trx_t* trx, /*!< in: transaction */
  923. bool read_write) /*!< in: true if read-write transaction */
  924. {
  925. ut_ad(!trx->in_rollback);
  926. ut_ad(!trx->is_recovered);
  927. ut_ad(trx->hit_list.empty());
  928. ut_ad(trx->start_line != 0);
  929. ut_ad(trx->start_file != 0);
  930. ut_ad(trx->roll_limit == 0);
  931. ut_ad(trx->error_state == DB_SUCCESS);
  932. ut_ad(trx->rsegs.m_redo.rseg == NULL);
  933. ut_ad(trx->rsegs.m_noredo.rseg == NULL);
  934. ut_ad(trx_state_eq(trx, TRX_STATE_NOT_STARTED));
  935. ut_ad(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
  936. ut_ad(!(trx->in_innodb & TRX_FORCE_ROLLBACK));
  937. ut_ad(!(trx->in_innodb & TRX_FORCE_ROLLBACK_ASYNC));
  938. ++trx->version;
  939. /* Check whether it is an AUTOCOMMIT SELECT */
  940. trx->auto_commit = thd_trx_is_auto_commit(trx->mysql_thd);
  941. trx->read_only = srv_read_only_mode
  942. || (!trx->ddl && !trx->internal
  943. && thd_trx_is_read_only(trx->mysql_thd));
  944. if (!trx->auto_commit) {
  945. ++trx->will_lock;
  946. } else if (trx->will_lock == 0) {
  947. trx->read_only = true;
  948. }
  949. #ifdef WITH_WSREP
  950. memset(trx->xid, 0, sizeof(xid_t));
  951. trx->xid->formatID = -1;
  952. #endif /* WITH_WSREP */
  953. /* The initial value for trx->no: TRX_ID_MAX is used in
  954. read_view_open_now: */
  955. trx->no = TRX_ID_MAX;
  956. ut_a(ib_vector_is_empty(trx->autoinc_locks));
  957. ut_a(trx->lock.table_locks.empty());
  958. /* If this transaction came from trx_allocate_for_mysql(),
  959. trx->in_mysql_trx_list would hold. In that case, the trx->state
  960. change must be protected by the trx_sys->mutex, so that
  961. lock_print_info_all_transactions() will have a consistent view. */
  962. ut_ad(!trx->in_rw_trx_list);
  963. /* We tend to over assert and that complicates the code somewhat.
  964. e.g., the transaction state can be set earlier but we are forced to
  965. set it under the protection of the trx_sys_t::mutex because some
  966. trx list assertions are triggered unnecessarily. */
  967. /* By default all transactions are in the read-only list unless they
  968. are non-locking auto-commit read only transactions or background
  969. (internal) transactions. Note: Transactions marked explicitly as
  970. read only can write to temporary tables, we put those on the RO
  971. list too. */
  972. if (!trx->read_only
  973. && (trx->mysql_thd == 0 || read_write || trx->ddl)) {
  974. trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
  975. /* Temporary rseg is assigned only if the transaction
  976. updates a temporary table */
  977. trx_sys_mutex_enter();
  978. trx->id = trx_sys_get_new_trx_id();
  979. trx_sys->rw_trx_ids.push_back(trx->id);
  980. trx_sys_rw_trx_add(trx);
  981. ut_ad(trx->rsegs.m_redo.rseg != 0
  982. || srv_read_only_mode
  983. || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
  984. UT_LIST_ADD_FIRST(trx_sys->rw_trx_list, trx);
  985. ut_d(trx->in_rw_trx_list = true);
  986. #ifdef UNIV_DEBUG
  987. if (trx->id > trx_sys->rw_max_trx_id) {
  988. trx_sys->rw_max_trx_id = trx->id;
  989. }
  990. #endif /* UNIV_DEBUG */
  991. trx->state = TRX_STATE_ACTIVE;
  992. ut_ad(trx_sys_validate_trx_list());
  993. trx_sys_mutex_exit();
  994. } else {
  995. trx->id = 0;
  996. if (!trx_is_autocommit_non_locking(trx)) {
  997. /* If this is a read-only transaction that is writing
  998. to a temporary table then it needs a transaction id
  999. to write to the temporary table. */
  1000. if (read_write) {
  1001. trx_sys_mutex_enter();
  1002. ut_ad(!srv_read_only_mode);
  1003. trx->id = trx_sys_get_new_trx_id();
  1004. trx_sys->rw_trx_ids.push_back(trx->id);
  1005. trx_sys->rw_trx_set.insert(
  1006. TrxTrack(trx->id, trx));
  1007. trx_sys_mutex_exit();
  1008. }
  1009. trx->state = TRX_STATE_ACTIVE;
  1010. } else {
  1011. ut_ad(!read_write);
  1012. trx->state = TRX_STATE_ACTIVE;
  1013. }
  1014. }
  1015. ut_usectime((ulong *)&trx->start_time,
  1016. (ulong *)&trx->start_time_micro);
  1017. if (trx->mysql_thd != NULL) {
  1018. time_t start_time = thd_start_time_in_secs(trx->mysql_thd);
  1019. ib_uint64_t start_utime = thd_query_start_micro(trx->mysql_thd);
  1020. if (start_time < trx->start_time ||
  1021. (start_time == trx->start_time && start_utime < trx->start_time_micro))
  1022. {
  1023. trx->start_time = start_time;
  1024. trx->start_time_micro = start_utime;
  1025. }
  1026. }
  1027. trx->vtq_notify_on_commit = false;
  1028. ut_a(trx->error_state == DB_SUCCESS);
  1029. MONITOR_INC(MONITOR_TRX_ACTIVE);
  1030. }
  1031. /** Set the serialisation number for a persistent committed transaction.
  1032. @param[in,out] trx committed transaction with persistent changes
  1033. @param[in,out] rseg rollback segment for update_undo, or NULL */
  1034. static
  1035. void
  1036. trx_serialise(trx_t* trx, trx_rseg_t* rseg)
  1037. {
  1038. ut_ad(!rseg || rseg == trx->rsegs.m_redo.rseg);
  1039. trx_sys_mutex_enter();
  1040. trx->no = trx_sys_get_new_trx_id();
  1041. /* Track the minimum serialisation number. */
  1042. UT_LIST_ADD_LAST(trx_sys->serialisation_list, trx);
  1043. /* If the rollack segment is not empty then the
  1044. new trx_t::no can't be less than any trx_t::no
  1045. already in the rollback segment. User threads only
  1046. produce events when a rollback segment is empty. */
  1047. if (rseg && rseg->last_page_no == FIL_NULL) {
  1048. TrxUndoRsegs elem(trx->no);
  1049. elem.push_back(rseg);
  1050. mutex_enter(&purge_sys->pq_mutex);
  1051. /* This is to reduce the pressure on the trx_sys_t::mutex
  1052. though in reality it should make very little (read no)
  1053. difference because this code path is only taken when the
  1054. rbs is empty. */
  1055. trx_sys_mutex_exit();
  1056. purge_sys->purge_queue.push(elem);
  1057. mutex_exit(&purge_sys->pq_mutex);
  1058. } else {
  1059. trx_sys_mutex_exit();
  1060. }
  1061. }
  1062. /****************************************************************//**
  1063. Assign the transaction its history serialisation number and write the
  1064. update UNDO log record to the assigned rollback segment.
  1065. @return true if a serialisation log was written */
  1066. static
  1067. bool
  1068. trx_write_serialisation_history(
  1069. /*============================*/
  1070. trx_t* trx, /*!< in/out: transaction */
  1071. mtr_t* mtr) /*!< in/out: mini-transaction */
  1072. {
  1073. /* Change the undo log segment states from TRX_UNDO_ACTIVE to some
  1074. other state: these modifications to the file data structure define
  1075. the transaction as committed in the file based domain, at the
  1076. serialization point of the log sequence number lsn obtained below. */
  1077. /* We have to hold the rseg mutex because update log headers have
  1078. to be put to the history list in the (serialisation) order of the
  1079. UNDO trx number. This is required for the purge in-memory data
  1080. structures too. */
  1081. if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) {
  1082. /* Undo log for temporary tables is discarded at transaction
  1083. commit. There is no purge for temporary tables, and also no
  1084. MVCC, because they are private to a session. */
  1085. mtr_t temp_mtr;
  1086. temp_mtr.start();
  1087. temp_mtr.set_log_mode(MTR_LOG_NO_REDO);
  1088. mutex_enter(&trx->rsegs.m_noredo.rseg->mutex);
  1089. trx_undo_set_state_at_finish(undo, &temp_mtr);
  1090. mutex_exit(&trx->rsegs.m_noredo.rseg->mutex);
  1091. temp_mtr.commit();
  1092. }
  1093. if (!trx->rsegs.m_redo.rseg) {
  1094. ut_ad(!trx->rsegs.m_redo.insert_undo);
  1095. ut_ad(!trx->rsegs.m_redo.update_undo);
  1096. return false;
  1097. }
  1098. trx_undo_t* insert = trx->rsegs.m_redo.insert_undo;
  1099. trx_undo_t* update = trx->rsegs.m_redo.update_undo;
  1100. if (!insert && !update) {
  1101. return false;
  1102. }
  1103. ut_ad(!trx->read_only);
  1104. trx_rseg_t* update_rseg = update ? trx->rsegs.m_redo.rseg : NULL;
  1105. mutex_enter(&trx->rsegs.m_redo.rseg->mutex);
  1106. /* Assign the transaction serialisation number and add any
  1107. update_undo log to the purge queue. */
  1108. trx_serialise(trx, update_rseg);
  1109. /* It is not necessary to acquire trx->undo_mutex here because
  1110. only a single OS thread is allowed to commit this transaction. */
  1111. if (insert) {
  1112. trx_undo_set_state_at_finish(insert, mtr);
  1113. }
  1114. if (update) {
  1115. /* The undo logs and possible delete-marked records
  1116. for updates and deletes will be purged later. */
  1117. page_t* undo_hdr_page = trx_undo_set_state_at_finish(
  1118. update, mtr);
  1119. trx_undo_update_cleanup(trx, undo_hdr_page, mtr);
  1120. }
  1121. mutex_exit(&trx->rsegs.m_redo.rseg->mutex);
  1122. MONITOR_INC(MONITOR_TRX_COMMIT_UNDO);
  1123. trx_sysf_t* sys_header = trx_sysf_get(mtr);
  1124. #ifdef WITH_WSREP
  1125. /* Update latest MySQL wsrep XID in trx sys header. */
  1126. if (wsrep_is_wsrep_xid(trx->xid)) {
  1127. trx_sys_update_wsrep_checkpoint(trx->xid, sys_header, mtr);
  1128. }
  1129. #endif /* WITH_WSREP */
  1130. /* Update the latest MySQL binlog name and offset info
  1131. in trx sys header if MySQL binlogging is on or the database
  1132. server is a MySQL replication slave */
  1133. if (trx->mysql_log_file_name != NULL
  1134. && trx->mysql_log_file_name[0] != '\0') {
  1135. trx_sys_update_mysql_binlog_offset(
  1136. trx->mysql_log_file_name,
  1137. trx->mysql_log_offset,
  1138. TRX_SYS_MYSQL_LOG_INFO,
  1139. sys_header,
  1140. mtr);
  1141. trx->mysql_log_file_name = NULL;
  1142. }
  1143. return(true);
  1144. }
  1145. /********************************************************************
  1146. Finalize a transaction containing updates for a FTS table. */
  1147. static
  1148. void
  1149. trx_finalize_for_fts_table(
  1150. /*=======================*/
  1151. fts_trx_table_t* ftt) /* in: FTS trx table */
  1152. {
  1153. fts_t* fts = ftt->table->fts;
  1154. fts_doc_ids_t* doc_ids = ftt->added_doc_ids;
  1155. mutex_enter(&fts->bg_threads_mutex);
  1156. if (fts->fts_status & BG_THREAD_STOP) {
  1157. /* The table is about to be dropped, no use
  1158. adding anything to its work queue. */
  1159. mutex_exit(&fts->bg_threads_mutex);
  1160. } else {
  1161. mem_heap_t* heap;
  1162. mutex_exit(&fts->bg_threads_mutex);
  1163. ut_a(fts->add_wq);
  1164. heap = static_cast<mem_heap_t*>(doc_ids->self_heap->arg);
  1165. ib_wqueue_add(fts->add_wq, doc_ids, heap);
  1166. /* fts_trx_table_t no longer owns the list. */
  1167. ftt->added_doc_ids = NULL;
  1168. }
  1169. }
  1170. /******************************************************************//**
  1171. Finalize a transaction containing updates to FTS tables. */
  1172. static
  1173. void
  1174. trx_finalize_for_fts(
  1175. /*=================*/
  1176. trx_t* trx, /*!< in/out: transaction */
  1177. bool is_commit) /*!< in: true if the transaction was
  1178. committed, false if it was rolled back. */
  1179. {
  1180. if (is_commit) {
  1181. const ib_rbt_node_t* node;
  1182. ib_rbt_t* tables;
  1183. fts_savepoint_t* savepoint;
  1184. savepoint = static_cast<fts_savepoint_t*>(
  1185. ib_vector_last(trx->fts_trx->savepoints));
  1186. tables = savepoint->tables;
  1187. for (node = rbt_first(tables);
  1188. node;
  1189. node = rbt_next(tables, node)) {
  1190. fts_trx_table_t** ftt;
  1191. ftt = rbt_value(fts_trx_table_t*, node);
  1192. if ((*ftt)->added_doc_ids) {
  1193. trx_finalize_for_fts_table(*ftt);
  1194. }
  1195. }
  1196. }
  1197. fts_trx_free(trx->fts_trx);
  1198. trx->fts_trx = NULL;
  1199. }
  1200. /**********************************************************************//**
  1201. If required, flushes the log to disk based on the value of
  1202. innodb_flush_log_at_trx_commit. */
  1203. static
  1204. void
  1205. trx_flush_log_if_needed_low(
  1206. /*========================*/
  1207. lsn_t lsn) /*!< in: lsn up to which logs are to be
  1208. flushed. */
  1209. {
  1210. bool flush = srv_file_flush_method != SRV_NOSYNC;
  1211. switch (srv_flush_log_at_trx_commit) {
  1212. case 3:
  1213. case 2:
  1214. /* Write the log but do not flush it to disk */
  1215. flush = false;
  1216. /* fall through */
  1217. case 1:
  1218. /* Write the log and optionally flush it to disk */
  1219. log_write_up_to(lsn, flush);
  1220. return;
  1221. case 0:
  1222. /* Do nothing */
  1223. return;
  1224. }
  1225. ut_error;
  1226. }
  1227. /**********************************************************************//**
  1228. If required, flushes the log to disk based on the value of
  1229. innodb_flush_log_at_trx_commit. */
  1230. static
  1231. void
  1232. trx_flush_log_if_needed(
  1233. /*====================*/
  1234. lsn_t lsn, /*!< in: lsn up to which logs are to be
  1235. flushed. */
  1236. trx_t* trx) /*!< in/out: transaction */
  1237. {
  1238. trx->op_info = "flushing log";
  1239. trx_flush_log_if_needed_low(lsn);
  1240. trx->op_info = "";
  1241. }
  1242. /**********************************************************************//**
  1243. For each table that has been modified by the given transaction: update
  1244. its dict_table_t::update_time with the current timestamp. Clear the list
  1245. of the modified tables at the end. */
  1246. static
  1247. void
  1248. trx_update_mod_tables_timestamp(
  1249. /*============================*/
  1250. trx_t* trx) /*!< in: transaction */
  1251. {
  1252. ut_ad(trx->id != 0);
  1253. /* consider using trx->start_time if calling time() is too
  1254. expensive here */
  1255. time_t now = ut_time();
  1256. trx_mod_tables_t::const_iterator end = trx->mod_tables.end();
  1257. for (trx_mod_tables_t::const_iterator it = trx->mod_tables.begin();
  1258. it != end;
  1259. ++it) {
  1260. /* This could be executed by multiple threads concurrently
  1261. on the same table object. This is fine because time_t is
  1262. word size or less. And _purely_ _theoretically_, even if
  1263. time_t write is not atomic, likely the value of 'now' is
  1264. the same in all threads and even if it is not, getting a
  1265. "garbage" in table->update_time is justified because
  1266. protecting it with a latch here would be too performance
  1267. intrusive. */
  1268. (*it)->update_time = now;
  1269. }
  1270. trx->mod_tables.clear();
  1271. }
  1272. /**
  1273. Erase the transaction from running transaction lists and serialization
  1274. list. Active RW transaction list of a MVCC snapshot(ReadView::prepare)
  1275. won't include this transaction after this call. All implicit locks are
  1276. also released by this call as trx is removed from rw_trx_list.
  1277. @param[in] trx Transaction to erase, must have an ID > 0
  1278. @param[in] serialised true if serialisation log was written */
  1279. static
  1280. void
  1281. trx_erase_lists(
  1282. trx_t* trx,
  1283. bool serialised)
  1284. {
  1285. ut_ad(trx->id > 0);
  1286. trx_sys_mutex_enter();
  1287. if (serialised) {
  1288. UT_LIST_REMOVE(trx_sys->serialisation_list, trx);
  1289. }
  1290. trx_ids_t::iterator it = std::lower_bound(
  1291. trx_sys->rw_trx_ids.begin(),
  1292. trx_sys->rw_trx_ids.end(),
  1293. trx->id);
  1294. ut_ad(*it == trx->id);
  1295. trx_sys->rw_trx_ids.erase(it);
  1296. if (trx->read_only || trx->rsegs.m_redo.rseg == NULL) {
  1297. ut_ad(!trx->in_rw_trx_list);
  1298. } else {
  1299. UT_LIST_REMOVE(trx_sys->rw_trx_list, trx);
  1300. ut_d(trx->in_rw_trx_list = false);
  1301. ut_ad(trx_sys_validate_trx_list());
  1302. if (trx->read_view != NULL) {
  1303. trx_sys->mvcc->view_close(trx->read_view, true);
  1304. }
  1305. }
  1306. trx_sys->rw_trx_set.erase(TrxTrack(trx->id));
  1307. trx_sys_mutex_exit();
  1308. }
  1309. /****************************************************************//**
  1310. Commits a transaction in memory. */
  1311. static
  1312. void
  1313. trx_commit_in_memory(
  1314. /*=================*/
  1315. trx_t* trx, /*!< in/out: transaction */
  1316. const mtr_t* mtr, /*!< in: mini-transaction of
  1317. trx_write_serialisation_history(), or NULL if
  1318. the transaction did not modify anything */
  1319. bool serialised)
  1320. /*!< in: true if serialisation log was
  1321. written */
  1322. {
  1323. trx->must_flush_log_later = false;
  1324. if (trx_is_autocommit_non_locking(trx)) {
  1325. ut_ad(trx->id == 0);
  1326. ut_ad(trx->read_only);
  1327. ut_a(!trx->is_recovered);
  1328. ut_ad(trx->rsegs.m_redo.rseg == NULL);
  1329. ut_ad(!trx->in_rw_trx_list);
  1330. /* Note: We are asserting without holding the lock mutex. But
  1331. that is OK because this transaction is not waiting and cannot
  1332. be rolled back and no new locks can (or should not) be added
  1333. becuase it is flagged as a non-locking read-only transaction. */
  1334. ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
  1335. /* This state change is not protected by any mutex, therefore
  1336. there is an inherent race here around state transition during
  1337. printouts. We ignore this race for the sake of efficiency.
  1338. However, the trx_sys_t::mutex will protect the trx_t instance
  1339. and it cannot be removed from the mysql_trx_list and freed
  1340. without first acquiring the trx_sys_t::mutex. */
  1341. ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
  1342. if (trx->read_view != NULL) {
  1343. trx_sys->mvcc->view_close(trx->read_view, false);
  1344. }
  1345. MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT);
  1346. /* AC-NL-RO transactions can't be rolled back asynchronously. */
  1347. ut_ad(!trx->abort);
  1348. ut_ad(!(trx->in_innodb
  1349. & (TRX_FORCE_ROLLBACK | TRX_FORCE_ROLLBACK_ASYNC)));
  1350. trx->state = TRX_STATE_NOT_STARTED;
  1351. } else {
  1352. if (trx->id > 0) {
  1353. /* For consistent snapshot, we need to remove current
  1354. transaction from running transaction id list for mvcc
  1355. before doing commit and releasing locks. */
  1356. trx_erase_lists(trx, serialised);
  1357. }
  1358. lock_trx_release_locks(trx);
  1359. /* Remove the transaction from the list of active
  1360. transactions now that it no longer holds any user locks. */
  1361. ut_ad(trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY));
  1362. DEBUG_SYNC_C("after_trx_committed_in_memory");
  1363. if (trx->read_only || trx->rsegs.m_redo.rseg == NULL) {
  1364. MONITOR_INC(MONITOR_TRX_RO_COMMIT);
  1365. if (trx->read_view != NULL) {
  1366. trx_sys->mvcc->view_close(
  1367. trx->read_view, false);
  1368. }
  1369. } else {
  1370. ut_ad(trx->id > 0);
  1371. MONITOR_INC(MONITOR_TRX_RW_COMMIT);
  1372. }
  1373. }
  1374. ut_ad(!trx->rsegs.m_redo.update_undo);
  1375. if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) {
  1376. mutex_enter(&rseg->mutex);
  1377. ut_ad(rseg->trx_ref_count > 0);
  1378. --rseg->trx_ref_count;
  1379. mutex_exit(&rseg->mutex);
  1380. if (trx_undo_t*& insert = trx->rsegs.m_redo.insert_undo) {
  1381. ut_ad(insert->rseg == rseg);
  1382. trx_undo_commit_cleanup(insert, false);
  1383. insert = NULL;
  1384. }
  1385. }
  1386. ut_ad(!trx->rsegs.m_redo.insert_undo);
  1387. if (mtr != NULL) {
  1388. if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) {
  1389. ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg);
  1390. trx_undo_commit_cleanup(undo, true);
  1391. undo = NULL;
  1392. }
  1393. /* NOTE that we could possibly make a group commit more
  1394. efficient here: call os_thread_yield here to allow also other
  1395. trxs to come to commit! */
  1396. /*-------------------------------------*/
  1397. /* Depending on the my.cnf options, we may now write the log
  1398. buffer to the log files, making the transaction durable if
  1399. the OS does not crash. We may also flush the log files to
  1400. disk, making the transaction durable also at an OS crash or a
  1401. power outage.
  1402. The idea in InnoDB's group commit is that a group of
  1403. transactions gather behind a trx doing a physical disk write
  1404. to log files, and when that physical write has been completed,
  1405. one of those transactions does a write which commits the whole
  1406. group. Note that this group commit will only bring benefit if
  1407. there are > 2 users in the database. Then at least 2 users can
  1408. gather behind one doing the physical log write to disk.
  1409. If we are calling trx_commit() under prepare_commit_mutex, we
  1410. will delay possible log write and flush to a separate function
  1411. trx_commit_complete_for_mysql(), which is only called when the
  1412. thread has released the mutex. This is to make the
  1413. group commit algorithm to work. Otherwise, the prepare_commit
  1414. mutex would serialize all commits and prevent a group of
  1415. transactions from gathering. */
  1416. lsn_t lsn = mtr->commit_lsn();
  1417. if (lsn == 0) {
  1418. /* Nothing to be done. */
  1419. } else if (trx->flush_log_later) {
  1420. /* Do nothing yet */
  1421. trx->must_flush_log_later = true;
  1422. } else if (srv_flush_log_at_trx_commit == 0
  1423. || thd_requested_durability(trx->mysql_thd)
  1424. == HA_IGNORE_DURABILITY) {
  1425. /* Do nothing */
  1426. } else {
  1427. trx_flush_log_if_needed(lsn, trx);
  1428. }
  1429. trx->commit_lsn = lsn;
  1430. /* Tell server some activity has happened, since the trx
  1431. does changes something. Background utility threads like
  1432. master thread, purge thread or page_cleaner thread might
  1433. have some work to do. */
  1434. srv_active_wake_master_thread();
  1435. }
  1436. ut_ad(!trx->rsegs.m_noredo.undo);
  1437. /* Free all savepoints, starting from the first. */
  1438. trx_named_savept_t* savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
  1439. trx_roll_savepoints_free(trx, savep);
  1440. if (trx->fts_trx != NULL) {
  1441. trx_finalize_for_fts(trx, trx->undo_no != 0);
  1442. }
  1443. trx_mutex_enter(trx);
  1444. trx->dict_operation = TRX_DICT_OP_NONE;
  1445. #ifdef WITH_WSREP
  1446. if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) {
  1447. trx->lock.was_chosen_as_deadlock_victim = FALSE;
  1448. }
  1449. #endif
  1450. /* Because we can rollback transactions asynchronously, we change
  1451. the state at the last step. trx_t::abort cannot change once commit
  1452. or rollback has started because we will have released the locks by
  1453. the time we get here. */
  1454. if (trx->abort) {
  1455. trx->abort = false;
  1456. trx->state = TRX_STATE_FORCED_ROLLBACK;
  1457. } else {
  1458. trx->state = TRX_STATE_NOT_STARTED;
  1459. }
  1460. /* trx->in_mysql_trx_list would hold between
  1461. trx_allocate_for_mysql() and trx_free_for_mysql(). It does not
  1462. hold for recovered transactions or system transactions. */
  1463. assert_trx_is_free(trx);
  1464. trx_init(trx);
  1465. trx_mutex_exit(trx);
  1466. ut_a(trx->error_state == DB_SUCCESS);
  1467. }
  1468. /****************************************************************//**
  1469. Commits a transaction and a mini-transaction. */
  1470. void
  1471. trx_commit_low(
  1472. /*===========*/
  1473. trx_t* trx, /*!< in/out: transaction */
  1474. mtr_t* mtr) /*!< in/out: mini-transaction (will be committed),
  1475. or NULL if trx made no modifications */
  1476. {
  1477. assert_trx_nonlocking_or_in_list(trx);
  1478. ut_ad(!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY));
  1479. ut_ad(!mtr || mtr->is_active());
  1480. ut_ad(!mtr == !trx->has_logged());
  1481. /* undo_no is non-zero if we're doing the final commit. */
  1482. if (trx->fts_trx != NULL && trx->undo_no != 0) {
  1483. dberr_t error;
  1484. ut_a(!trx_is_autocommit_non_locking(trx));
  1485. error = fts_commit(trx);
  1486. /* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY
  1487. instead of dying. This is a possible scenario if there
  1488. is a crash between insert to DELETED table committing
  1489. and transaction committing. The fix would be able to
  1490. return error from this function */
  1491. if (error != DB_SUCCESS && error != DB_DUPLICATE_KEY) {
  1492. /* FTS-FIXME: once we can return values from this
  1493. function, we should do so and signal an error
  1494. instead of just dying. */
  1495. ut_error;
  1496. }
  1497. }
  1498. bool serialised;
  1499. if (mtr != NULL) {
  1500. mtr->set_sync();
  1501. serialised = trx_write_serialisation_history(trx, mtr);
  1502. /* The following call commits the mini-transaction, making the
  1503. whole transaction committed in the file-based world, at this
  1504. log sequence number. The transaction becomes 'durable' when
  1505. we write the log to disk, but in the logical sense the commit
  1506. in the file-based data structures (undo logs etc.) happens
  1507. here.
  1508. NOTE that transaction numbers, which are assigned only to
  1509. transactions with an update undo log, do not necessarily come
  1510. in exactly the same order as commit lsn's, if the transactions
  1511. have different rollback segments. To get exactly the same
  1512. order we should hold the kernel mutex up to this point,
  1513. adding to the contention of the kernel mutex. However, if
  1514. a transaction T2 is able to see modifications made by
  1515. a transaction T1, T2 will always get a bigger transaction
  1516. number and a bigger commit lsn than T1. */
  1517. /*--------------*/
  1518. mtr_commit(mtr);
  1519. DBUG_EXECUTE_IF("ib_crash_during_trx_commit_in_mem",
  1520. if (trx->has_logged()) {
  1521. log_make_checkpoint_at(LSN_MAX, TRUE);
  1522. DBUG_SUICIDE();
  1523. });
  1524. /*--------------*/
  1525. } else {
  1526. serialised = false;
  1527. }
  1528. #ifndef DBUG_OFF
  1529. /* In case of this function is called from a stack executing
  1530. THD::release_resources -> ...
  1531. innobase_connection_close() ->
  1532. trx_rollback_for_mysql... -> .
  1533. mysql's thd does not seem to have
  1534. thd->debug_sync_control defined any longer. However the stack
  1535. is possible only with a prepared trx not updating any data.
  1536. */
  1537. if (trx->mysql_thd != NULL && trx->has_logged_persistent()) {
  1538. DEBUG_SYNC_C("before_trx_state_committed_in_memory");
  1539. }
  1540. #endif
  1541. trx_commit_in_memory(trx, mtr, serialised);
  1542. }
  1543. /****************************************************************//**
  1544. Commits a transaction. */
  1545. void
  1546. trx_commit(
  1547. /*=======*/
  1548. trx_t* trx) /*!< in/out: transaction */
  1549. {
  1550. mtr_t* mtr;
  1551. mtr_t local_mtr;
  1552. DBUG_EXECUTE_IF("ib_trx_commit_crash_before_trx_commit_start",
  1553. DBUG_SUICIDE(););
  1554. if (trx->has_logged()) {
  1555. mtr = &local_mtr;
  1556. mtr_start_sync(mtr);
  1557. } else {
  1558. mtr = NULL;
  1559. }
  1560. trx_commit_low(trx, mtr);
  1561. }
  1562. /****************************************************************//**
  1563. Cleans up a transaction at database startup. The cleanup is needed if
  1564. the transaction already got to the middle of a commit when the database
  1565. crashed, and we cannot roll it back. */
  1566. void
  1567. trx_cleanup_at_db_startup(
  1568. /*======================*/
  1569. trx_t* trx) /*!< in: transaction */
  1570. {
  1571. ut_ad(trx->is_recovered);
  1572. ut_ad(!trx->rsegs.m_noredo.undo);
  1573. ut_ad(!trx->rsegs.m_redo.update_undo);
  1574. if (trx_undo_t*& undo = trx->rsegs.m_redo.insert_undo) {
  1575. ut_ad(undo->rseg == trx->rsegs.m_redo.rseg);
  1576. trx_undo_commit_cleanup(undo, false);
  1577. undo = NULL;
  1578. }
  1579. memset(&trx->rsegs, 0x0, sizeof(trx->rsegs));
  1580. trx->undo_no = 0;
  1581. trx->undo_rseg_space = 0;
  1582. trx->last_sql_stat_start.least_undo_no = 0;
  1583. trx_sys_mutex_enter();
  1584. ut_a(!trx->read_only);
  1585. UT_LIST_REMOVE(trx_sys->rw_trx_list, trx);
  1586. ut_d(trx->in_rw_trx_list = FALSE);
  1587. trx_sys_mutex_exit();
  1588. /* Change the transaction state without mutex protection, now
  1589. that it no longer is in the trx_list. Recovered transactions
  1590. are never placed in the mysql_trx_list. */
  1591. ut_ad(trx->is_recovered);
  1592. ut_ad(!trx->in_rw_trx_list);
  1593. ut_ad(!trx->in_mysql_trx_list);
  1594. trx->state = TRX_STATE_NOT_STARTED;
  1595. }
  1596. /********************************************************************//**
  1597. Assigns a read view for a consistent read query. All the consistent reads
  1598. within the same transaction will get the same read view, which is created
  1599. when this function is first called for a new started transaction.
  1600. @return consistent read view */
  1601. ReadView*
  1602. trx_assign_read_view(
  1603. /*=================*/
  1604. trx_t* trx) /*!< in/out: active transaction */
  1605. {
  1606. ut_ad(trx->state == TRX_STATE_ACTIVE);
  1607. if (srv_read_only_mode) {
  1608. ut_ad(trx->read_view == NULL);
  1609. return(NULL);
  1610. } else if (!MVCC::is_view_active(trx->read_view)) {
  1611. trx_sys->mvcc->view_open(trx->read_view, trx);
  1612. }
  1613. return(trx->read_view);
  1614. }
  1615. /****************************************************************//**
  1616. Prepares a transaction for commit/rollback. */
  1617. void
  1618. trx_commit_or_rollback_prepare(
  1619. /*===========================*/
  1620. trx_t* trx) /*!< in/out: transaction */
  1621. {
  1622. /* We are reading trx->state without holding trx_sys->mutex
  1623. here, because the commit or rollback should be invoked for a
  1624. running (or recovered prepared) transaction that is associated
  1625. with the current thread. */
  1626. switch (trx->state) {
  1627. case TRX_STATE_NOT_STARTED:
  1628. case TRX_STATE_FORCED_ROLLBACK:
  1629. trx_start_low(trx, true);
  1630. /* fall through */
  1631. case TRX_STATE_ACTIVE:
  1632. case TRX_STATE_PREPARED:
  1633. /* If the trx is in a lock wait state, moves the waiting
  1634. query thread to the suspended state */
  1635. if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
  1636. ut_a(trx->lock.wait_thr != NULL);
  1637. trx->lock.wait_thr->state = QUE_THR_SUSPENDED;
  1638. trx->lock.wait_thr = NULL;
  1639. trx->lock.que_state = TRX_QUE_RUNNING;
  1640. }
  1641. ut_a(trx->lock.n_active_thrs == 1);
  1642. return;
  1643. case TRX_STATE_COMMITTED_IN_MEMORY:
  1644. break;
  1645. }
  1646. ut_error;
  1647. }
  1648. /*********************************************************************//**
  1649. Creates a commit command node struct.
  1650. @return own: commit node struct */
  1651. commit_node_t*
  1652. trx_commit_node_create(
  1653. /*===================*/
  1654. mem_heap_t* heap) /*!< in: mem heap where created */
  1655. {
  1656. commit_node_t* node;
  1657. node = static_cast<commit_node_t*>(mem_heap_alloc(heap, sizeof(*node)));
  1658. node->common.type = QUE_NODE_COMMIT;
  1659. node->state = COMMIT_NODE_SEND;
  1660. return(node);
  1661. }
  1662. /***********************************************************//**
  1663. Performs an execution step for a commit type node in a query graph.
  1664. @return query thread to run next, or NULL */
  1665. que_thr_t*
  1666. trx_commit_step(
  1667. /*============*/
  1668. que_thr_t* thr) /*!< in: query thread */
  1669. {
  1670. commit_node_t* node;
  1671. node = static_cast<commit_node_t*>(thr->run_node);
  1672. ut_ad(que_node_get_type(node) == QUE_NODE_COMMIT);
  1673. if (thr->prev_node == que_node_get_parent(node)) {
  1674. node->state = COMMIT_NODE_SEND;
  1675. }
  1676. if (node->state == COMMIT_NODE_SEND) {
  1677. trx_t* trx;
  1678. node->state = COMMIT_NODE_WAIT;
  1679. trx = thr_get_trx(thr);
  1680. ut_a(trx->lock.wait_thr == NULL);
  1681. ut_a(trx->lock.que_state != TRX_QUE_LOCK_WAIT);
  1682. trx_commit_or_rollback_prepare(trx);
  1683. trx->lock.que_state = TRX_QUE_COMMITTING;
  1684. trx_commit(trx);
  1685. ut_ad(trx->lock.wait_thr == NULL);
  1686. trx->lock.que_state = TRX_QUE_RUNNING;
  1687. thr = NULL;
  1688. } else {
  1689. ut_ad(node->state == COMMIT_NODE_WAIT);
  1690. node->state = COMMIT_NODE_SEND;
  1691. thr->run_node = que_node_get_parent(node);
  1692. }
  1693. return(thr);
  1694. }
  1695. /**********************************************************************//**
  1696. Does the transaction commit for MySQL.
  1697. @return DB_SUCCESS or error number */
  1698. dberr_t
  1699. trx_commit_for_mysql(
  1700. /*=================*/
  1701. trx_t* trx) /*!< in/out: transaction */
  1702. {
  1703. TrxInInnoDB trx_in_innodb(trx, true);
  1704. if (trx_in_innodb.is_aborted()
  1705. && trx->killed_by != os_thread_get_curr_id()) {
  1706. return(DB_FORCED_ABORT);
  1707. }
  1708. /* Because we do not do the commit by sending an Innobase
  1709. sig to the transaction, we must here make sure that trx has been
  1710. started. */
  1711. switch (trx->state) {
  1712. case TRX_STATE_NOT_STARTED:
  1713. case TRX_STATE_FORCED_ROLLBACK:
  1714. ut_d(trx->start_file = __FILE__);
  1715. ut_d(trx->start_line = __LINE__);
  1716. trx_start_low(trx, true);
  1717. /* fall through */
  1718. case TRX_STATE_ACTIVE:
  1719. case TRX_STATE_PREPARED:
  1720. trx->op_info = "committing";
  1721. if (trx->id != 0) {
  1722. trx_update_mod_tables_timestamp(trx);
  1723. }
  1724. trx_commit(trx);
  1725. MONITOR_DEC(MONITOR_TRX_ACTIVE);
  1726. trx->op_info = "";
  1727. return(DB_SUCCESS);
  1728. case TRX_STATE_COMMITTED_IN_MEMORY:
  1729. break;
  1730. }
  1731. ut_error;
  1732. return(DB_CORRUPTION);
  1733. }
  1734. /**********************************************************************//**
  1735. If required, flushes the log to disk if we called trx_commit_for_mysql()
  1736. with trx->flush_log_later == TRUE. */
  1737. void
  1738. trx_commit_complete_for_mysql(
  1739. /*==========================*/
  1740. trx_t* trx) /*!< in/out: transaction */
  1741. {
  1742. if (trx->id != 0
  1743. || !trx->must_flush_log_later
  1744. || thd_requested_durability(trx->mysql_thd)
  1745. == HA_IGNORE_DURABILITY) {
  1746. return;
  1747. }
  1748. trx_flush_log_if_needed(trx->commit_lsn, trx);
  1749. trx->must_flush_log_later = false;
  1750. }
  1751. /**********************************************************************//**
  1752. Marks the latest SQL statement ended. */
  1753. void
  1754. trx_mark_sql_stat_end(
  1755. /*==================*/
  1756. trx_t* trx) /*!< in: trx handle */
  1757. {
  1758. ut_a(trx);
  1759. switch (trx->state) {
  1760. case TRX_STATE_PREPARED:
  1761. case TRX_STATE_COMMITTED_IN_MEMORY:
  1762. break;
  1763. case TRX_STATE_NOT_STARTED:
  1764. case TRX_STATE_FORCED_ROLLBACK:
  1765. trx->undo_no = 0;
  1766. trx->undo_rseg_space = 0;
  1767. /* fall through */
  1768. case TRX_STATE_ACTIVE:
  1769. trx->last_sql_stat_start.least_undo_no = trx->undo_no;
  1770. if (trx->fts_trx != NULL) {
  1771. fts_savepoint_laststmt_refresh(trx);
  1772. }
  1773. return;
  1774. }
  1775. ut_error;
  1776. }
  1777. /**********************************************************************//**
  1778. Prints info about a transaction.
  1779. Caller must hold trx_sys->mutex. */
  1780. void
  1781. trx_print_low(
  1782. /*==========*/
  1783. FILE* f,
  1784. /*!< in: output stream */
  1785. const trx_t* trx,
  1786. /*!< in: transaction */
  1787. ulint max_query_len,
  1788. /*!< in: max query length to print,
  1789. or 0 to use the default max length */
  1790. ulint n_rec_locks,
  1791. /*!< in: lock_number_of_rows_locked(&trx->lock) */
  1792. ulint n_trx_locks,
  1793. /*!< in: length of trx->lock.trx_locks */
  1794. ulint heap_size)
  1795. /*!< in: mem_heap_get_size(trx->lock.lock_heap) */
  1796. {
  1797. ibool newline;
  1798. const char* op_info;
  1799. ut_ad(trx_sys_mutex_own());
  1800. fprintf(f, "TRANSACTION " TRX_ID_FMT, trx_get_id_for_print(trx));
  1801. /* trx->state cannot change from or to NOT_STARTED while we
  1802. are holding the trx_sys->mutex. It may change from ACTIVE to
  1803. PREPARED or COMMITTED. */
  1804. switch (trx->state) {
  1805. case TRX_STATE_NOT_STARTED:
  1806. fputs(", not started", f);
  1807. goto state_ok;
  1808. case TRX_STATE_FORCED_ROLLBACK:
  1809. fputs(", forced rollback", f);
  1810. goto state_ok;
  1811. case TRX_STATE_ACTIVE:
  1812. fprintf(f, ", ACTIVE %lu sec",
  1813. (ulong) difftime(time(NULL), trx->start_time));
  1814. goto state_ok;
  1815. case TRX_STATE_PREPARED:
  1816. fprintf(f, ", ACTIVE (PREPARED) %lu sec",
  1817. (ulong) difftime(time(NULL), trx->start_time));
  1818. goto state_ok;
  1819. case TRX_STATE_COMMITTED_IN_MEMORY:
  1820. fputs(", COMMITTED IN MEMORY", f);
  1821. goto state_ok;
  1822. }
  1823. fprintf(f, ", state %lu", (ulong) trx->state);
  1824. ut_ad(0);
  1825. state_ok:
  1826. /* prevent a race condition */
  1827. op_info = trx->op_info;
  1828. if (*op_info) {
  1829. putc(' ', f);
  1830. fputs(op_info, f);
  1831. }
  1832. if (trx->is_recovered) {
  1833. fputs(" recovered trx", f);
  1834. }
  1835. if (trx->declared_to_be_inside_innodb) {
  1836. fprintf(f, ", thread declared inside InnoDB %lu",
  1837. (ulong) trx->n_tickets_to_enter_innodb);
  1838. }
  1839. putc('\n', f);
  1840. if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) {
  1841. fprintf(f, "mysql tables in use %lu, locked %lu\n",
  1842. (ulong) trx->n_mysql_tables_in_use,
  1843. (ulong) trx->mysql_n_tables_locked);
  1844. }
  1845. newline = TRUE;
  1846. /* trx->lock.que_state of an ACTIVE transaction may change
  1847. while we are not holding trx->mutex. We perform a dirty read
  1848. for performance reasons. */
  1849. switch (trx->lock.que_state) {
  1850. case TRX_QUE_RUNNING:
  1851. newline = FALSE; break;
  1852. case TRX_QUE_LOCK_WAIT:
  1853. fputs("LOCK WAIT ", f); break;
  1854. case TRX_QUE_ROLLING_BACK:
  1855. fputs("ROLLING BACK ", f); break;
  1856. case TRX_QUE_COMMITTING:
  1857. fputs("COMMITTING ", f); break;
  1858. default:
  1859. fprintf(f, "que state %lu ", (ulong) trx->lock.que_state);
  1860. }
  1861. if (n_trx_locks > 0 || heap_size > 400) {
  1862. newline = TRUE;
  1863. fprintf(f, "%lu lock struct(s), heap size %lu,"
  1864. " %lu row lock(s)",
  1865. (ulong) n_trx_locks,
  1866. (ulong) heap_size,
  1867. (ulong) n_rec_locks);
  1868. }
  1869. #ifdef BTR_CUR_HASH_ADAPT
  1870. if (trx->has_search_latch) {
  1871. newline = TRUE;
  1872. fputs(", holds adaptive hash latch", f);
  1873. }
  1874. #endif /* BTR_CUR_HASH_ADAPT */
  1875. if (trx->undo_no != 0) {
  1876. newline = TRUE;
  1877. fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no);
  1878. }
  1879. if (newline) {
  1880. putc('\n', f);
  1881. }
  1882. if (trx->state != TRX_STATE_NOT_STARTED && trx->mysql_thd != NULL) {
  1883. innobase_mysql_print_thd(
  1884. f, trx->mysql_thd, static_cast<uint>(max_query_len));
  1885. }
  1886. }
  1887. /**********************************************************************//**
  1888. Prints info about a transaction.
  1889. The caller must hold lock_sys->mutex and trx_sys->mutex.
  1890. When possible, use trx_print() instead. */
  1891. void
  1892. trx_print_latched(
  1893. /*==============*/
  1894. FILE* f, /*!< in: output stream */
  1895. const trx_t* trx, /*!< in: transaction */
  1896. ulint max_query_len) /*!< in: max query length to print,
  1897. or 0 to use the default max length */
  1898. {
  1899. ut_ad(lock_mutex_own());
  1900. ut_ad(trx_sys_mutex_own());
  1901. trx_print_low(f, trx, max_query_len,
  1902. lock_number_of_rows_locked(&trx->lock),
  1903. UT_LIST_GET_LEN(trx->lock.trx_locks),
  1904. mem_heap_get_size(trx->lock.lock_heap));
  1905. }
  1906. /**********************************************************************//**
  1907. Prints info about a transaction.
  1908. Acquires and releases lock_sys->mutex and trx_sys->mutex. */
  1909. void
  1910. trx_print(
  1911. /*======*/
  1912. FILE* f, /*!< in: output stream */
  1913. const trx_t* trx, /*!< in: transaction */
  1914. ulint max_query_len) /*!< in: max query length to print,
  1915. or 0 to use the default max length */
  1916. {
  1917. ulint n_rec_locks;
  1918. ulint n_trx_locks;
  1919. ulint heap_size;
  1920. lock_mutex_enter();
  1921. n_rec_locks = lock_number_of_rows_locked(&trx->lock);
  1922. n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks);
  1923. heap_size = mem_heap_get_size(trx->lock.lock_heap);
  1924. lock_mutex_exit();
  1925. mutex_enter(&trx_sys->mutex);
  1926. trx_print_low(f, trx, max_query_len,
  1927. n_rec_locks, n_trx_locks, heap_size);
  1928. mutex_exit(&trx_sys->mutex);
  1929. }
  1930. #ifdef UNIV_DEBUG
  1931. /**********************************************************************//**
  1932. Asserts that a transaction has been started.
  1933. The caller must hold trx_sys->mutex.
  1934. @return TRUE if started */
  1935. ibool
  1936. trx_assert_started(
  1937. /*===============*/
  1938. const trx_t* trx) /*!< in: transaction */
  1939. {
  1940. ut_ad(trx_sys_mutex_own());
  1941. /* Non-locking autocommits should not hold any locks and this
  1942. function is only called from the locking code. */
  1943. check_trx_state(trx);
  1944. /* trx->state can change from or to NOT_STARTED while we are holding
  1945. trx_sys->mutex for non-locking autocommit selects but not for other
  1946. types of transactions. It may change from ACTIVE to PREPARED. Unless
  1947. we are holding lock_sys->mutex, it may also change to COMMITTED. */
  1948. switch (trx->state) {
  1949. case TRX_STATE_PREPARED:
  1950. return(TRUE);
  1951. case TRX_STATE_ACTIVE:
  1952. case TRX_STATE_COMMITTED_IN_MEMORY:
  1953. return(TRUE);
  1954. case TRX_STATE_NOT_STARTED:
  1955. case TRX_STATE_FORCED_ROLLBACK:
  1956. break;
  1957. }
  1958. ut_error;
  1959. return(FALSE);
  1960. }
  1961. #endif /* UNIV_DEBUG */
  1962. /*******************************************************************//**
  1963. Compares the "weight" (or size) of two transactions. Transactions that
  1964. have edited non-transactional tables are considered heavier than ones
  1965. that have not.
  1966. @return TRUE if weight(a) >= weight(b) */
  1967. bool
  1968. trx_weight_ge(
  1969. /*==========*/
  1970. const trx_t* a, /*!< in: transaction to be compared */
  1971. const trx_t* b) /*!< in: transaction to be compared */
  1972. {
  1973. ibool a_notrans_edit;
  1974. ibool b_notrans_edit;
  1975. /* If mysql_thd is NULL for a transaction we assume that it has
  1976. not edited non-transactional tables. */
  1977. a_notrans_edit = a->mysql_thd != NULL
  1978. && thd_has_edited_nontrans_tables(a->mysql_thd);
  1979. b_notrans_edit = b->mysql_thd != NULL
  1980. && thd_has_edited_nontrans_tables(b->mysql_thd);
  1981. if (a_notrans_edit != b_notrans_edit) {
  1982. return(a_notrans_edit);
  1983. }
  1984. /* Either both had edited non-transactional tables or both had
  1985. not, we fall back to comparing the number of altered/locked
  1986. rows. */
  1987. return(TRX_WEIGHT(a) >= TRX_WEIGHT(b));
  1988. }
  1989. /** Prepare a transaction.
  1990. @return log sequence number that makes the XA PREPARE durable
  1991. @retval 0 if no changes needed to be made durable */
  1992. static
  1993. lsn_t
  1994. trx_prepare_low(trx_t* trx)
  1995. {
  1996. mtr_t mtr;
  1997. /* It is not necessary to acquire trx->undo_mutex here because
  1998. only the owning (connection) thread of the transaction is
  1999. allowed to perform XA PREPARE. */
  2000. if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) {
  2001. ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg);
  2002. mtr.start();
  2003. mtr.set_log_mode(MTR_LOG_NO_REDO);
  2004. mutex_enter(&undo->rseg->mutex);
  2005. trx_undo_set_state_at_prepare(trx, undo, false, &mtr);
  2006. mutex_exit(&undo->rseg->mutex);
  2007. mtr.commit();
  2008. }
  2009. trx_undo_t* insert = trx->rsegs.m_redo.insert_undo;
  2010. trx_undo_t* update = trx->rsegs.m_redo.update_undo;
  2011. if (!insert && !update) {
  2012. /* There were no changes to persistent tables. */
  2013. return(0);
  2014. }
  2015. trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
  2016. mtr.start(true);
  2017. /* Change the undo log segment states from TRX_UNDO_ACTIVE to
  2018. TRX_UNDO_PREPARED: these modifications to the file data
  2019. structure define the transaction as prepared in the file-based
  2020. world, at the serialization point of lsn. */
  2021. mutex_enter(&rseg->mutex);
  2022. if (insert) {
  2023. ut_ad(insert->rseg == rseg);
  2024. trx_undo_set_state_at_prepare(trx, insert, false, &mtr);
  2025. }
  2026. if (update) {
  2027. ut_ad(update->rseg == rseg);
  2028. trx_undo_set_state_at_prepare(trx, update, false, &mtr);
  2029. }
  2030. mutex_exit(&rseg->mutex);
  2031. /* Make the XA PREPARE durable. */
  2032. mtr.commit();
  2033. ut_ad(mtr.commit_lsn() > 0);
  2034. return(mtr.commit_lsn());
  2035. }
  2036. /****************************************************************//**
  2037. Prepares a transaction. */
  2038. static
  2039. void
  2040. trx_prepare(
  2041. /*========*/
  2042. trx_t* trx) /*!< in/out: transaction */
  2043. {
  2044. /* This transaction has crossed the point of no return and cannot
  2045. be rolled back asynchronously now. It must commit or rollback
  2046. synhronously. */
  2047. /* Only fresh user transactions can be prepared.
  2048. Recovered transactions cannot. */
  2049. ut_a(!trx->is_recovered);
  2050. lsn_t lsn = trx_prepare_low(trx);
  2051. DBUG_EXECUTE_IF("ib_trx_crash_during_xa_prepare_step", DBUG_SUICIDE(););
  2052. /*--------------------------------------*/
  2053. ut_a(trx->state == TRX_STATE_ACTIVE);
  2054. trx_sys_mutex_enter();
  2055. trx->state = TRX_STATE_PREPARED;
  2056. trx_sys->n_prepared_trx++;
  2057. trx_sys_mutex_exit();
  2058. /*--------------------------------------*/
  2059. switch (thd_requested_durability(trx->mysql_thd)) {
  2060. case HA_IGNORE_DURABILITY:
  2061. /* We set the HA_IGNORE_DURABILITY during prepare phase of
  2062. binlog group commit to not flush redo log for every transaction
  2063. here. So that we can flush prepared records of transactions to
  2064. redo log in a group right before writing them to binary log
  2065. during flush stage of binlog group commit. */
  2066. break;
  2067. case HA_REGULAR_DURABILITY:
  2068. if (lsn == 0) {
  2069. break;
  2070. }
  2071. /* Depending on the my.cnf options, we may now write the log
  2072. buffer to the log files, making the prepared state of the
  2073. transaction durable if the OS does not crash. We may also
  2074. flush the log files to disk, making the prepared state of the
  2075. transaction durable also at an OS crash or a power outage.
  2076. The idea in InnoDB's group prepare is that a group of
  2077. transactions gather behind a trx doing a physical disk write
  2078. to log files, and when that physical write has been completed,
  2079. one of those transactions does a write which prepares the whole
  2080. group. Note that this group prepare will only bring benefit if
  2081. there are > 2 users in the database. Then at least 2 users can
  2082. gather behind one doing the physical log write to disk.
  2083. We must not be holding any mutexes or latches here. */
  2084. trx_flush_log_if_needed(lsn, trx);
  2085. }
  2086. }
  2087. /**
  2088. Does the transaction prepare for MySQL.
  2089. @param[in, out] trx Transaction instance to prepare */
  2090. dberr_t
  2091. trx_prepare_for_mysql(trx_t* trx)
  2092. {
  2093. trx_start_if_not_started_xa(trx, false);
  2094. TrxInInnoDB trx_in_innodb(trx, true);
  2095. if (trx_in_innodb.is_aborted()
  2096. && trx->killed_by != os_thread_get_curr_id()) {
  2097. return(DB_FORCED_ABORT);
  2098. }
  2099. trx->op_info = "preparing";
  2100. trx_prepare(trx);
  2101. trx->op_info = "";
  2102. return(DB_SUCCESS);
  2103. }
  2104. /**********************************************************************//**
  2105. This function is used to find number of prepared transactions and
  2106. their transaction objects for a recovery.
  2107. @return number of prepared transactions stored in xid_list */
  2108. int
  2109. trx_recover_for_mysql(
  2110. /*==================*/
  2111. XID* xid_list, /*!< in/out: prepared transactions */
  2112. ulint len) /*!< in: number of slots in xid_list */
  2113. {
  2114. const trx_t* trx;
  2115. ulint count = 0;
  2116. ut_ad(xid_list);
  2117. ut_ad(len);
  2118. /* We should set those transactions which are in the prepared state
  2119. to the xid_list */
  2120. trx_sys_mutex_enter();
  2121. for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
  2122. trx != NULL;
  2123. trx = UT_LIST_GET_NEXT(trx_list, trx)) {
  2124. assert_trx_in_rw_list(trx);
  2125. /* The state of a read-write transaction cannot change
  2126. from or to NOT_STARTED while we are holding the
  2127. trx_sys->mutex. It may change to PREPARED, but not if
  2128. trx->is_recovered. It may also change to COMMITTED. */
  2129. if (trx_state_eq(trx, TRX_STATE_PREPARED)) {
  2130. xid_list[count] = *trx->xid;
  2131. if (count == 0) {
  2132. ib::info() << "Starting recovery for"
  2133. " XA transactions...";
  2134. }
  2135. ib::info() << "Transaction "
  2136. << trx_get_id_for_print(trx)
  2137. << " in prepared state after recovery";
  2138. ib::info() << "Transaction contains changes to "
  2139. << trx->undo_no << " rows";
  2140. count++;
  2141. if (count == len) {
  2142. break;
  2143. }
  2144. }
  2145. }
  2146. trx_sys_mutex_exit();
  2147. if (count > 0){
  2148. ib::info() << count << " transactions in prepared state"
  2149. " after recovery";
  2150. }
  2151. return(int (count));
  2152. }
  2153. /*******************************************************************//**
  2154. This function is used to find one X/Open XA distributed transaction
  2155. which is in the prepared state
  2156. @return trx on match, the trx->xid will be invalidated;
  2157. note that the trx may have been committed, unless the caller is
  2158. holding lock_sys->mutex */
  2159. static MY_ATTRIBUTE((warn_unused_result))
  2160. trx_t*
  2161. trx_get_trx_by_xid_low(
  2162. /*===================*/
  2163. XID* xid) /*!< in: X/Open XA transaction
  2164. identifier */
  2165. {
  2166. trx_t* trx;
  2167. ut_ad(trx_sys_mutex_own());
  2168. for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
  2169. trx != NULL;
  2170. trx = UT_LIST_GET_NEXT(trx_list, trx)) {
  2171. assert_trx_in_rw_list(trx);
  2172. /* Compare two X/Open XA transaction id's: their
  2173. length should be the same and binary comparison
  2174. of gtrid_length+bqual_length bytes should be
  2175. the same */
  2176. if (trx->is_recovered
  2177. && trx_state_eq(trx, TRX_STATE_PREPARED)
  2178. && xid->eq((XID*)trx->xid)) {
  2179. /* Invalidate the XID, so that subsequent calls
  2180. will not find it. */
  2181. trx->xid->null();
  2182. break;
  2183. }
  2184. }
  2185. return(trx);
  2186. }
  2187. /*******************************************************************//**
  2188. This function is used to find one X/Open XA distributed transaction
  2189. which is in the prepared state
  2190. @return trx or NULL; on match, the trx->xid will be invalidated;
  2191. note that the trx may have been committed, unless the caller is
  2192. holding lock_sys->mutex */
  2193. trx_t*
  2194. trx_get_trx_by_xid(
  2195. /*===============*/
  2196. XID* xid) /*!< in: X/Open XA transaction identifier */
  2197. {
  2198. trx_t* trx;
  2199. if (xid == NULL) {
  2200. return(NULL);
  2201. }
  2202. trx_sys_mutex_enter();
  2203. /* Recovered/Resurrected transactions are always only on the
  2204. trx_sys_t::rw_trx_list. */
  2205. trx = trx_get_trx_by_xid_low((XID*)xid);
  2206. trx_sys_mutex_exit();
  2207. return(trx);
  2208. }
  2209. /*************************************************************//**
  2210. Starts the transaction if it is not yet started. */
  2211. void
  2212. trx_start_if_not_started_xa_low(
  2213. /*============================*/
  2214. trx_t* trx, /*!< in/out: transaction */
  2215. bool read_write) /*!< in: true if read write transaction */
  2216. {
  2217. switch (trx->state) {
  2218. case TRX_STATE_NOT_STARTED:
  2219. case TRX_STATE_FORCED_ROLLBACK:
  2220. trx_start_low(trx, read_write);
  2221. return;
  2222. case TRX_STATE_ACTIVE:
  2223. if (trx->id == 0 && read_write) {
  2224. /* If the transaction is tagged as read-only then
  2225. it can only write to temp tables and for such
  2226. transactions we don't want to move them to the
  2227. trx_sys_t::rw_trx_list. */
  2228. if (!trx->read_only) {
  2229. trx_set_rw_mode(trx);
  2230. }
  2231. }
  2232. return;
  2233. case TRX_STATE_PREPARED:
  2234. case TRX_STATE_COMMITTED_IN_MEMORY:
  2235. break;
  2236. }
  2237. ut_error;
  2238. }
  2239. /*************************************************************//**
  2240. Starts the transaction if it is not yet started. */
  2241. void
  2242. trx_start_if_not_started_low(
  2243. /*==========================*/
  2244. trx_t* trx, /*!< in: transaction */
  2245. bool read_write) /*!< in: true if read write transaction */
  2246. {
  2247. switch (trx->state) {
  2248. case TRX_STATE_NOT_STARTED:
  2249. case TRX_STATE_FORCED_ROLLBACK:
  2250. trx_start_low(trx, read_write);
  2251. return;
  2252. case TRX_STATE_ACTIVE:
  2253. if (read_write && trx->id == 0 && !trx->read_only) {
  2254. trx_set_rw_mode(trx);
  2255. }
  2256. return;
  2257. case TRX_STATE_PREPARED:
  2258. case TRX_STATE_COMMITTED_IN_MEMORY:
  2259. break;
  2260. }
  2261. ut_error;
  2262. }
  2263. /*************************************************************//**
  2264. Starts a transaction for internal processing. */
  2265. void
  2266. trx_start_internal_low(
  2267. /*===================*/
  2268. trx_t* trx) /*!< in/out: transaction */
  2269. {
  2270. /* Ensure it is not flagged as an auto-commit-non-locking
  2271. transaction. */
  2272. trx->will_lock = 1;
  2273. trx->internal = true;
  2274. trx_start_low(trx, true);
  2275. }
  2276. /** Starts a read-only transaction for internal processing.
  2277. @param[in,out] trx transaction to be started */
  2278. void
  2279. trx_start_internal_read_only_low(
  2280. trx_t* trx)
  2281. {
  2282. /* Ensure it is not flagged as an auto-commit-non-locking
  2283. transaction. */
  2284. trx->will_lock = 1;
  2285. trx->internal = true;
  2286. trx_start_low(trx, false);
  2287. }
  2288. /*************************************************************//**
  2289. Starts the transaction for a DDL operation. */
  2290. void
  2291. trx_start_for_ddl_low(
  2292. /*==================*/
  2293. trx_t* trx, /*!< in/out: transaction */
  2294. trx_dict_op_t op) /*!< in: dictionary operation type */
  2295. {
  2296. switch (trx->state) {
  2297. case TRX_STATE_NOT_STARTED:
  2298. case TRX_STATE_FORCED_ROLLBACK:
  2299. /* Flag this transaction as a dictionary operation, so that
  2300. the data dictionary will be locked in crash recovery. */
  2301. trx_set_dict_operation(trx, op);
  2302. /* Ensure it is not flagged as an auto-commit-non-locking
  2303. transation. */
  2304. trx->will_lock = 1;
  2305. trx->ddl= true;
  2306. trx_start_internal_low(trx);
  2307. return;
  2308. case TRX_STATE_ACTIVE:
  2309. /* We have this start if not started idiom, therefore we
  2310. can't add stronger checks here. */
  2311. trx->ddl = true;
  2312. ut_ad(trx->dict_operation != TRX_DICT_OP_NONE);
  2313. ut_ad(trx->will_lock > 0);
  2314. return;
  2315. case TRX_STATE_PREPARED:
  2316. case TRX_STATE_COMMITTED_IN_MEMORY:
  2317. break;
  2318. }
  2319. ut_error;
  2320. }
  2321. /*************************************************************//**
  2322. Set the transaction as a read-write transaction if it is not already
  2323. tagged as such. Read-only transactions that are writing to temporary
  2324. tables are assigned an ID and a rollback segment but are not added
  2325. to the trx read-write list because their updates should not be visible
  2326. to other transactions and therefore their changes can be ignored by
  2327. by MVCC. */
  2328. void
  2329. trx_set_rw_mode(
  2330. /*============*/
  2331. trx_t* trx) /*!< in/out: transaction that is RW */
  2332. {
  2333. ut_ad(trx->rsegs.m_redo.rseg == 0);
  2334. ut_ad(!trx->in_rw_trx_list);
  2335. ut_ad(!trx_is_autocommit_non_locking(trx));
  2336. if (srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO) {
  2337. return;
  2338. }
  2339. /* Function is promoting existing trx from ro mode to rw mode.
  2340. In this process it has acquired trx_sys->mutex as it plan to
  2341. move trx from ro list to rw list. If in future, some other thread
  2342. looks at this trx object while it is being promoted then ensure
  2343. that both threads are synced by acquring trx->mutex to avoid decision
  2344. based on in-consistent view formed during promotion. */
  2345. trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
  2346. ut_ad(trx->rsegs.m_redo.rseg != 0);
  2347. mutex_enter(&trx_sys->mutex);
  2348. ut_ad(trx->id == 0);
  2349. trx->id = trx_sys_get_new_trx_id();
  2350. trx_sys->rw_trx_ids.push_back(trx->id);
  2351. trx_sys->rw_trx_set.insert(TrxTrack(trx->id, trx));
  2352. /* So that we can see our own changes. */
  2353. if (MVCC::is_view_active(trx->read_view)) {
  2354. MVCC::set_view_creator_trx_id(trx->read_view, trx->id);
  2355. }
  2356. #ifdef UNIV_DEBUG
  2357. if (trx->id > trx_sys->rw_max_trx_id) {
  2358. trx_sys->rw_max_trx_id = trx->id;
  2359. }
  2360. #endif /* UNIV_DEBUG */
  2361. if (!trx->read_only) {
  2362. UT_LIST_ADD_FIRST(trx_sys->rw_trx_list, trx);
  2363. ut_d(trx->in_rw_trx_list = true);
  2364. }
  2365. mutex_exit(&trx_sys->mutex);
  2366. }
  2367. /**
  2368. Kill all transactions that are blocking this transaction from acquiring locks.
  2369. @param[in,out] trx High priority transaction */
  2370. void
  2371. trx_kill_blocking(trx_t* trx)
  2372. {
  2373. if (trx->hit_list.empty()) {
  2374. return;
  2375. }
  2376. DEBUG_SYNC_C("trx_kill_blocking_enter");
  2377. ulint had_dict_lock = trx->dict_operation_lock_mode;
  2378. switch (had_dict_lock) {
  2379. case 0:
  2380. break;
  2381. case RW_S_LATCH:
  2382. /* Release foreign key check latch */
  2383. row_mysql_unfreeze_data_dictionary(trx);
  2384. break;
  2385. default:
  2386. /* There should never be a lock wait when the
  2387. dictionary latch is reserved in X mode. Dictionary
  2388. transactions should only acquire locks on dictionary
  2389. tables, not other tables. All access to dictionary
  2390. tables should be covered by dictionary
  2391. transactions. */
  2392. ut_error;
  2393. }
  2394. ut_a(trx->dict_operation_lock_mode == 0);
  2395. /** Kill the transactions in the lock acquisition order old -> new. */
  2396. hit_list_t::reverse_iterator end = trx->hit_list.rend();
  2397. for (hit_list_t::reverse_iterator it = trx->hit_list.rbegin();
  2398. it != end;
  2399. ++it) {
  2400. trx_t* victim_trx = it->m_trx;
  2401. ulint version = it->m_version;
  2402. /* Shouldn't commit suicide. */
  2403. ut_ad(victim_trx != trx);
  2404. ut_ad(victim_trx->mysql_thd != trx->mysql_thd);
  2405. /* Check that the transaction isn't active inside
  2406. InnoDB code. We have to wait while it is executing
  2407. in the InnoDB context. This can potentially take a
  2408. long time */
  2409. trx_mutex_enter(victim_trx);
  2410. ut_ad(version <= victim_trx->version);
  2411. ulint loop_count = 0;
  2412. /* start with optimistic sleep time of 20 micro seconds. */
  2413. ulint sleep_time = 20;
  2414. while ((victim_trx->in_innodb & TRX_FORCE_ROLLBACK_MASK) > 0
  2415. && victim_trx->version == version) {
  2416. trx_mutex_exit(victim_trx);
  2417. loop_count++;
  2418. /* If the wait is long, don't hog the cpu. */
  2419. if (loop_count < 100) {
  2420. /* 20 microseconds */
  2421. sleep_time = 20;
  2422. } else if (loop_count < 1000) {
  2423. /* 1 millisecond */
  2424. sleep_time = 1000;
  2425. } else {
  2426. /* 100 milliseconds */
  2427. sleep_time = 100000;
  2428. }
  2429. os_thread_sleep(sleep_time);
  2430. trx_mutex_enter(victim_trx);
  2431. }
  2432. /* Compare the version to check if the transaction has
  2433. already finished */
  2434. if (victim_trx->version != version) {
  2435. trx_mutex_exit(victim_trx);
  2436. continue;
  2437. }
  2438. /* We should never kill background transactions. */
  2439. ut_ad(victim_trx->mysql_thd != NULL);
  2440. ut_ad(!(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE));
  2441. ut_ad(victim_trx->in_innodb & TRX_FORCE_ROLLBACK);
  2442. ut_ad(victim_trx->in_innodb & TRX_FORCE_ROLLBACK_ASYNC);
  2443. ut_ad(victim_trx->killed_by == os_thread_get_curr_id());
  2444. ut_ad(victim_trx->version == it->m_version);
  2445. /* We don't kill Read Only, Background or high priority
  2446. transactions. */
  2447. ut_a(!victim_trx->read_only);
  2448. ut_a(victim_trx->mysql_thd != NULL);
  2449. trx_mutex_exit(victim_trx);
  2450. #ifndef DBUG_OFF
  2451. char buffer[1024];
  2452. #endif /* !DBUG_OFF */
  2453. DBUG_LOG("trx",
  2454. "High Priority Transaction "
  2455. << trx->id << " killed transaction "
  2456. << victim_trx->id << " in hit list"
  2457. << " - "
  2458. << thd_get_error_context_description(
  2459. victim_trx->mysql_thd,
  2460. buffer, sizeof(buffer), 512));
  2461. trx_rollback_for_mysql(victim_trx);
  2462. trx_mutex_enter(victim_trx);
  2463. version++;
  2464. ut_ad(victim_trx->version == version);
  2465. my_atomic_storelong(&victim_trx->killed_by, 0);
  2466. victim_trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK;
  2467. trx_mutex_exit(victim_trx);
  2468. }
  2469. trx->hit_list.clear();
  2470. if (had_dict_lock) {
  2471. row_mysql_freeze_data_dictionary(trx);
  2472. }
  2473. }