From: magnus.blaudd Date: April 25 2012 12:36pm Subject: bzr push into mysql-trunk branch (magnus.blaudd:3735 to 3736) WL#5906 List-Archive: http://lists.mysql.com/commits/143657 Message-Id: <201204251236.q3PCaAuC023741@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3736 magnus.blaudd@stripped 2012-04-25 WL#5906 read before write removal (RBWR) - Adapt patch to latest trunk. - Since both update and delete now does all the checks in one place, the common code has been factored out into TABLE::check_read_removal() which is then called both from mysql_update() and mysql_delete() - Remove handler::read_before_write_removal_supported() in favor of using the HA_READ_BEFORE_WRITE_REMOVAL table flag. - Rename handler::read_before_write_removal_rows_written() to handler::end_read_removal() - Rename handler::read_before_write_removal_possible() to handler::start_read_removal() - Remove unnecessary DBUG printouts modified: sql/ha_ndbcluster.cc sql/ha_ndbcluster.h sql/handler.h sql/sql_delete.cc sql/sql_update.cc sql/table.cc sql/table.h 3735 magnus.blaudd@stripped 2012-04-25 [merge] Merge trunk-wl5906 with trunk modified: sql/handler.h sql/sql_delete.cc sql/sql_update.cc === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2012-03-28 11:25:37 +0000 +++ b/sql/ha_ndbcluster.cc 2012-04-25 12:30:33 +0000 @@ -7138,10 +7138,10 @@ int ha_ndbcluster::extra(enum ha_extra_f } -bool ha_ndbcluster::read_before_write_removal_possible() +bool ha_ndbcluster::start_read_removal() { THD *thd= table->in_use; - DBUG_ENTER("read_before_write_removal_possible"); + DBUG_ENTER("start_read_removal"); if (uses_blob_value(table->write_set)) { @@ -7188,9 +7188,10 @@ bool ha_ndbcluster::read_before_write_re } -ha_rows ha_ndbcluster::read_before_write_removal_rows_written(void) const +ha_rows ha_ndbcluster::end_read_removal(void) { - DBUG_ENTER("read_before_write_removal_rows_written"); + DBUG_ENTER("end_read_removal"); + DBUG_ASSERT(m_read_before_write_removal_possible); DBUG_PRINT("info", ("updated: %llu, deleted: %llu", m_rows_updated, m_rows_deleted)); DBUG_RETURN(m_rows_updated + m_rows_deleted); === modified file 'sql/ha_ndbcluster.h' --- a/sql/ha_ndbcluster.h 2012-03-28 11:25:37 +0000 +++ b/sql/ha_ndbcluster.h 2012-04-25 12:30:33 +0000 @@ -305,9 +305,8 @@ class ha_ndbcluster: public handler #endif void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id); uint32 calculate_key_hash_value(Field **field_array); - bool read_before_write_removal_supported() const { return true; } - bool read_before_write_removal_possible(); - ha_rows read_before_write_removal_rows_written(void) const; + bool start_read_removal(void); + ha_rows end_read_removal(void); int extra(enum ha_extra_function operation); int extra_opt(enum ha_extra_function operation, ulong cache_size); int reset(); === modified file 'sql/handler.h' --- a/sql/handler.h 2012-04-25 07:05:16 +0000 +++ b/sql/handler.h 2012-04-25 12:30:33 +0000 @@ -2169,27 +2169,23 @@ public: virtual int extra_opt(enum ha_extra_function operation, ulong cache_size) { return extra(operation); } - /** - Informs handler that it is possible to optimize away the real read - operation from the handler for the current table and instead - use a generated read to optimze simple UPDATEs and DELETEs. - - @return true if handler supports rbwr for this write + /* + Start read (before write) removal on the current table. Fake rows may + be returned while reading from the selected index. This is used to + optimise simple UPDATE and DELETEs.The handler may refuse to start + due to internal limitations in the storage engine. Successful start + is always followed by end. + Function will only be called for handles who returns + HA_READ_BEFORE_WRITE_REMOVAL from table_flags() */ - virtual bool read_before_write_removal_possible(void) - { return false; } + virtual bool start_read_removal(void) + { DBUG_ASSERT(0); return false; } - /** - Return the number of rows the handler has written while using - read before write removal - - @return the number of rows actually written - */ - virtual ha_rows read_before_write_removal_rows_written(void) const - { - DBUG_ASSERT(false); - return (ha_rows) 0; - } + /* + End read (before write) removal and return the number of rows really written + */ + virtual ha_rows end_read_removal(void) + { DBUG_ASSERT(0); return (ha_rows) 0; } /** In an UPDATE or DELETE, if the row under the cursor was locked by another === modified file 'sql/sql_delete.cc' --- a/sql/sql_delete.cc 2012-04-25 07:05:16 +0000 +++ b/sql/sql_delete.cc 2012-04-25 12:30:33 +0000 @@ -343,35 +343,13 @@ bool mysql_delete(THD *thd, TABLE_LIST * else will_batch= !table->file->start_bulk_delete(); - /* - Read removal is possible if the selected quick read - method is using full unique index - */ - if (table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL && - select && select->quick && - will_batch && - !thd->lex->ignore && - !using_limit) - { - const uint idx = select->quick->index; - DBUG_PRINT("rbwr", ("checking index: %d", idx)); - const KEY *key= table->key_info + idx; - if (key->flags & HA_NOSAME) - { - DBUG_PRINT("rbwr", ("index is unique")); - bitmap_clear_all(&table->tmp_set); - table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set); - if (bitmap_cmp(&table->tmp_set, table->read_set)) - { - DBUG_PRINT("rbwr", ("using whole index, rbwr possible")); - read_removal= - table->file->read_before_write_removal_possible(); - } - } - } - table->mark_columns_needed_for_delete(); + if ((table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL) && + !using_limit && + select && select->quick && select->quick->index != MAX_KEY) + read_removal= table->check_read_removal(select->quick->index); + while (!(error=info.read_record(&info)) && !thd->killed && ! thd->is_error()) { @@ -434,9 +412,7 @@ bool mysql_delete(THD *thd, TABLE_LIST * if (read_removal) { /* Only handler knows how many records were really written */ - DBUG_PRINT("rbwr", ("old deleted: %ld", (long)deleted)); - deleted= table->file->read_before_write_removal_rows_written(); - DBUG_PRINT("rbwr", ("really deleted: %ld", (long)deleted)); + deleted= table->file->end_read_removal(); } THD_STAGE_INFO(thd, stage_end); end_read_record(&info); === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2012-04-25 07:05:16 +0000 +++ b/sql/sql_update.cc 2012-04-25 12:30:33 +0000 @@ -474,35 +474,6 @@ int mysql_update(THD *thd, } } // Ends scope for optimizer trace wrapper - /* - Read removal is possible if the selected quick read - method is using full unique index - - NOTE! table->read_set currently holds the columns which are - used for the WHERE clause(this info is most likely already - available in select->quick, but where?) - */ - if (table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL && - select && select->quick && select->quick->index != MAX_KEY && - !ignore && - !using_limit) - { - const uint idx= select->quick->index; - DBUG_PRINT("rbwr", ("checking index: %d", idx)); - const KEY *key= table->key_info + idx; - if (key->flags & HA_NOSAME) - { - DBUG_PRINT("rbwr", ("index is unique")); - bitmap_clear_all(&table->tmp_set); - table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set); - if (bitmap_cmp(&table->tmp_set, table->read_set)) - { - DBUG_PRINT("rbwr", ("using full index, rbwr possible")); - read_removal= true; - } - } - } - /* If running in safe sql mode, don't allow updates without keys */ if (table->quick_keys.is_clear_all()) { @@ -688,10 +659,6 @@ int mysql_update(THD *thd, } if (used_index < MAX_KEY && old_covering_keys.is_set(used_index)) table->set_keyread(false); - - /* Rows are already read -> not possible to remove */ - DBUG_PRINT("rbwr", ("rows are already read, turning off rbwr")); - read_removal= false; } if (ignore) @@ -730,13 +697,11 @@ int mysql_update(THD *thd, else will_batch= !table->file->start_bulk_update(); - if (read_removal && - will_batch && + if ((table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL) && + !ignore && !using_limit && + select && select->quick && select->quick->index != MAX_KEY && check_constant_expressions(values)) - { - DBUG_ASSERT(select && select->quick); - read_removal= table->file->read_before_write_removal_possible(); - } + read_removal= table->check_read_removal(select->quick->index); // For prepare_record_for_error_message(): if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) @@ -952,15 +917,9 @@ int mysql_update(THD *thd, if (read_removal) { /* Only handler knows how many records really was written */ - DBUG_PRINT("rbwr", ("adjusting updated: %ld, found: %ld", - (long)updated, (long)found)); - - updated= table->file->read_before_write_removal_rows_written(); + updated= table->file->end_read_removal(); if (!records_are_comparable(table)) found= updated; - - DBUG_PRINT("rbwr", ("really updated: %ld, found: %ld", - (long)updated, (long)found)); } if (!transactional_table && updated > 0) === modified file 'sql/table.cc' --- a/sql/table.cc 2012-04-18 13:06:39 +0000 +++ b/sql/table.cc 2012-04-25 12:30:33 +0000 @@ -5997,6 +5997,37 @@ Field *TABLE::get_timestamp_field() } +/* + Read removal is possible if the selected quick read + method is using full unique index + + @param index Number of the index used for read + + @retval true success, read removal started + @retval false read removal not started +*/ + +bool TABLE::check_read_removal(uint index) +{ + DBUG_ENTER("check_read_removal"); + DBUG_ASSERT(file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL); + DBUG_ASSERT(index != MAX_KEY); + + // Index must be unique + if ((key_info[index].flags & HA_NOSAME) == 0) + DBUG_RETURN(false); + + // Full index must be used + bitmap_clear_all(&tmp_set); + mark_columns_used_by_index_no_reset(index, &tmp_set); + if (!bitmap_cmp(&tmp_set, read_set)) + DBUG_RETURN(false); + + // Start read removal in handler + DBUG_RETURN(file->start_read_removal()); +} + + /** Test if the order list consists of simple field expressions === modified file 'sql/table.h' --- a/sql/table.h 2012-04-16 09:26:56 +0000 +++ b/sql/table.h 2012-04-25 12:30:33 +0000 @@ -1157,6 +1157,8 @@ public: Field *get_timestamp_field(); bool update_const_key_parts(Item *conds); + + bool check_read_removal(uint index); }; No bundle (reason: useless for push emails).