From: Mattias Jonsson Date: May 29 2012 10:15pm Subject: bzr push into mysql-trunk branch (mattias.jonsson:3910 to 3911) WL#4443 List-Archive: http://lists.mysql.com/commits/144019 Message-Id: <201205292215.q4TMFcG9001026@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3911 Mattias Jonsson 2012-05-30 WL#4443: final code change for dlenevs review. - Don't use pruning in lock_count(). - Don't use pruning in store_lock() if not owning thd. - Renamed is_fields_used_in_trigger to is_fields_updated_in_trigger() and check if they may be updated. - moved out mark_fields_used(TRG_EVENT_UPDATE) from mark_columns_needed_for_update(). And reverted the changed call order. And call mark_fields_used(TRG_EVENT_UPDATE) instead. modified: mysql-test/r/partition_locking.result mysql-test/t/partition_locking.test sql/ha_partition.cc sql/partition_info.cc sql/sql_trigger.cc sql/sql_trigger.h sql/sql_update.cc sql/table.cc 3910 Mattias Jonsson 2012-05-29 [merge] WL#4443: Manual merge into latest mysql-trunk. also fixed the HA_OPEN_NO_PSI_CALL check. removed: mysql-test/r/grant_cache_ps_prot.result mysql-test/t/grant_cache_ps_prot.test added: mysql-test/collections/mysql-trunk-wl4443.push mysql-test/include/partition_default_functions.inc mysql-test/r/partition_locking.result mysql-test/t/partition_locking.test renamed: mysql-test/r/grant_cache_no_prot.result => mysql-test/r/grant_cache.result mysql-test/t/grant_cache_no_prot.test => mysql-test/t/grant_cache.test modified: include/my_base.h include/my_bitmap.h include/my_time.h mysql-test/include/commit.inc mysql-test/include/grant_cache.inc mysql-test/include/handler.inc mysql-test/r/commit_1innodb.result mysql-test/r/explain.result mysql-test/r/func_if.result mysql-test/r/handler_innodb.result mysql-test/r/handler_myisam.result mysql-test/r/innodb_explain_json_non_select_all.result mysql-test/r/innodb_explain_json_non_select_none.result mysql-test/r/innodb_explain_non_select_all.result mysql-test/r/innodb_explain_non_select_none.result mysql-test/r/myisam_explain_json_non_select_all.result mysql-test/r/myisam_explain_json_non_select_none.result mysql-test/r/myisam_explain_non_select_all.result mysql-test/r/myisam_explain_non_select_none.result mysql-test/r/partition_binlog.result mysql-test/r/partition_explicit_prune.result mysql-test/r/partition_pruning.result mysql-test/r/partition_truncate.result mysql-test/r/type_date.result mysql-test/suite/binlog/r/binlog_unsafe.result mysql-test/suite/opt_trace/r/bugs_no_prot_all.result mysql-test/suite/opt_trace/r/bugs_no_prot_none.result mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result mysql-test/suite/parts/inc/partition-dml-1-9.inc mysql-test/suite/parts/r/partition-dml-1-9-innodb.result mysql-test/suite/parts/r/partition-dml-1-9-myisam.result mysql-test/suite/parts/r/partition_debug_sync_innodb.result mysql-test/suite/parts/t/partition_debug_sync_innodb.test mysql-test/suite/perfschema/r/part_table_io.result mysql-test/suite/perfschema/r/stage_mdl_function.result mysql-test/t/explain.test mysql-test/t/partition_binlog.test mysql-test/t/partition_explicit_prune.test mysql-test/t/partition_pruning.test mysql-test/t/partition_truncate.test mysql-test/t/type_date.test mysys/my_bitmap.c sql/ha_ndbcluster.cc sql/ha_partition.cc sql/ha_partition.h sql/handler.cc sql/handler.h sql/item.cc sql/item.h sql/item_cmpfunc.cc sql/item_func.cc sql/item_strfunc.h sql/item_subselect.cc sql/opt_explain.cc sql/opt_range.cc sql/partition_info.cc sql/partition_info.h sql/rpl_info_table_access.cc sql/share/errmsg-utf8.txt sql/sp.cc sql/sql_base.cc sql/sql_base.h sql/sql_cache.h sql/sql_class.h sql/sql_data_change.h sql/sql_delete.cc sql/sql_executor.cc sql/sql_handler.cc sql/sql_insert.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_optimizer.cc sql/sql_parse.cc sql/sql_parse.h sql/sql_partition.cc sql/sql_partition.h sql/sql_partition_admin.cc sql/sql_prepare.cc sql/sql_resolver.cc sql/sql_select.cc sql/sql_select.h sql/sql_show.cc sql/sql_tmp_table.cc sql/sql_trigger.cc sql/sql_trigger.h sql/sql_union.cc sql/sql_update.cc sql/sql_view.cc sql/table.cc sql/table.h unittest/gunit/my_bitmap-t.cc mysql-test/r/grant_cache.result mysql-test/t/grant_cache.test === modified file 'mysql-test/r/partition_locking.result' --- a/mysql-test/r/partition_locking.result revid:mattias.jonsson@stripped +++ b/mysql-test/r/partition_locking.result revid:mattias.jonsson@stripped @@ -4453,11 +4453,11 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 -HANDLER_EXTERNAL_LOCK 28 +HANDLER_EXTERNAL_LOCK 4 HANDLER_READ_KEY 1 HANDLER_UPDATE 1 HANDLER_WRITE 18 -# 28 locks (1 tables, 13 partitions lock/unlock) +# 4 locks (1 tables, 1 partitions lock/unlock) FLUSH STATUS; UPDATE t1 SET b = CONCAT(b, ", Updated") WHERE a = 0; SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS === modified file 'mysql-test/t/partition_locking.test' --- a/mysql-test/t/partition_locking.test revid:mattias.jonsson@stripped +++ b/mysql-test/t/partition_locking.test revid:mattias.jonsson@stripped @@ -1606,7 +1606,7 @@ FLUSH STATUS; INSERT INTO t1 VALUES (0, "2nd p0") ON DUPLICATE KEY UPDATE b = CONCAT(b, ", dup key"); eval $get_handler_status_counts; ---echo # 28 locks (1 tables, 13 partitions lock/unlock) +--echo # 4 locks (1 tables, 1 partitions lock/unlock) FLUSH STATUS; UPDATE t1 SET b = CONCAT(b, ", Updated") WHERE a = 0; === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc revid:mattias.jonsson@stripped +++ b/sql/ha_partition.cc revid:mattias.jonsson@stripped @@ -3491,13 +3491,27 @@ THR_LOCK_DATA **ha_partition::store_lock { uint i; DBUG_ENTER("ha_partition::store_lock"); + DBUG_ASSERT(thd == current_thd); - for (i= bitmap_get_first_set(&(m_part_info->lock_partitions)); - i < m_tot_parts; - i= bitmap_get_next_set(&m_part_info->lock_partitions, i)) + /* + This can be called from get_lock_data() in mysql_lock_abort_for_thread(), + even when thd != table->in_use. In that case don't use partition pruning, + but use all partitions instead to avoid using another threads structures. + */ + if (thd != table->in_use) + { + for (i= 0; i < m_tot_parts; i++) + to= m_file[i]->store_lock(thd, to, lock_type); + } + else { - DBUG_PRINT("info", ("store lock %d iteration", i)); - to= m_file[i]->store_lock(thd, to, lock_type); + for (i= bitmap_get_first_set(&(m_part_info->lock_partitions)); + i < m_tot_parts; + i= bitmap_get_next_set(&m_part_info->lock_partitions, i)) + { + DBUG_PRINT("info", ("store lock %d iteration", i)); + to= m_file[i]->store_lock(thd, to, lock_type); + } } DBUG_RETURN(to); } @@ -3563,13 +3577,16 @@ int ha_partition::start_stmt(THD *thd, t uint ha_partition::lock_count() const { DBUG_ENTER("ha_partition::lock_count"); - DBUG_PRINT("info", ("m_num_locks %d total %d", m_num_locks, - bitmap_bits_set(&m_part_info->lock_partitions) * m_num_locks)); /* - We choose to return the exact count to avoid allocating unused memory, - even if the cpu cost of bitmap_bits_set is linear: O(number of partitions). + The caller want to know the upper bound, to allocate enough memory. + There is no performance lost if we simply return maximum number locks + needed, only some minor over allocation of memory in get_lock_data(). + + Also notice that this may be called for another thread != table->in_use, + when mysql_lock_abort_for_thread() is called. So this is more safe, then + using number of partitions after pruning. */ - DBUG_RETURN(bitmap_bits_set(&m_part_info->lock_partitions) * m_num_locks); + DBUG_RETURN(m_tot_parts * m_num_locks); } === modified file 'sql/partition_info.cc' --- a/sql/partition_info.cc revid:mattias.jonsson@stripped +++ b/sql/partition_info.cc revid:mattias.jonsson@stripped @@ -284,9 +284,9 @@ bool partition_info::can_prune_insert(TH */ if (table->triggers && table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE) && - table->triggers->is_fields_used_in_trigger(&full_part_field_set, - TRG_EVENT_INSERT, - TRG_ACTION_BEFORE)) + table->triggers->is_fields_updated_in_trigger(&full_part_field_set, + TRG_EVENT_INSERT, + TRG_ACTION_BEFORE)) DBUG_RETURN(false); if (table->found_next_number_field) @@ -333,9 +333,9 @@ bool partition_info::can_prune_insert(TH if (table->triggers && table->triggers->has_triggers(TRG_EVENT_UPDATE, TRG_ACTION_BEFORE) && - table->triggers->is_fields_used_in_trigger(&full_part_field_set, - TRG_EVENT_UPDATE, - TRG_ACTION_BEFORE)) + table->triggers->is_fields_updated_in_trigger(&full_part_field_set, + TRG_EVENT_UPDATE, + TRG_ACTION_BEFORE)) { DBUG_RETURN(false); } === modified file 'sql/sql_trigger.cc' --- a/sql/sql_trigger.cc revid:mattias.jonsson@stripped +++ b/sql/sql_trigger.cc revid:mattias.jonsson@stripped @@ -2218,9 +2218,9 @@ add_tables_and_routines_for_triggers(THD @param action_time Type of trigger action time we are going to inspect */ -bool Table_triggers_list::is_fields_used_in_trigger(MY_BITMAP *used_fields, - trg_event_type event_type, - trg_action_time_type action_time) +bool Table_triggers_list::is_fields_updated_in_trigger(MY_BITMAP *used_fields, + trg_event_type event_type, + trg_action_time_type action_time) { Item_trigger_field *trg_field; sp_head *sp= bodies[event_type][action_time]; @@ -2232,7 +2232,8 @@ bool Table_triggers_list::is_fields_used /* We cannot check fields which does not present in table. */ if (trg_field->field_idx != (uint)-1) { - if (bitmap_is_set(used_fields, trg_field->field_idx)) + if (bitmap_is_set(used_fields, trg_field->field_idx) && + trg_field->get_settable_routine_parameter()) return true; } } === modified file 'sql/sql_trigger.h' --- a/sql/sql_trigger.h revid:mattias.jonsson@stripped +++ b/sql/sql_trigger.h revid:mattias.jonsson@stripped @@ -210,9 +210,9 @@ public: bool add_tables_and_routines_for_triggers(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list); - bool is_fields_used_in_trigger(MY_BITMAP *used_fields, - trg_event_type event_type, - trg_action_time_type action_time); + bool is_fields_updated_in_trigger(MY_BITMAP *used_fields, + trg_event_type event_type, + trg_action_time_type action_time); private: bool prepare_record1_accessors(); LEX_STRING* change_table_name_in_trignames(const char *old_db_name, === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc revid:mattias.jonsson@stripped +++ b/sql/sql_update.cc revid:mattias.jonsson@stripped @@ -412,7 +412,8 @@ int mysql_update(THD *thd, This must be done before partitioning pruning, since prune_partitions() uses the table->write_set to determine may prune locks too. */ - table->mark_columns_needed_for_update(); + if (table->triggers) + table->triggers->mark_fields_used(TRG_EVENT_UPDATE); #ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info) @@ -439,6 +440,7 @@ int mysql_update(THD *thd, /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + table->mark_columns_needed_for_update(); select= make_select(table, 0, 0, conds, 0, &error); { // Enter scope for optimizer trace wrapper @@ -1680,7 +1682,8 @@ int multi_update::prepare(List &no bitmap_union(table->read_set, table->write_set); } /* All needed columns must be marked before prune_partitions(). */ - table->mark_columns_needed_for_update(); + if (table->triggers) + table->triggers->mark_fields_used(TRG_EVENT_UPDATE); } } === modified file 'sql/table.cc' --- a/sql/table.cc revid:mattias.jonsson@stripped +++ b/sql/table.cc revid:mattias.jonsson@stripped @@ -5063,8 +5063,6 @@ void TABLE::mark_columns_needed_for_upda DBUG_ENTER("mark_columns_needed_for_update"); mark_columns_per_binlog_row_image(); - if (triggers) - triggers->mark_fields_used(TRG_EVENT_UPDATE); if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE) { /* Mark all used key columns for read */ No bundle (reason: useless for push emails).