From be63f0af4f46048eda18bd66300949a810f0fd1e Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 8 Sep 2008 15:30:01 +0200 Subject: Bug#38804: Query deadlock causes all tables to be inaccessible. Problem was a mutex added in bug n 27405 for solving a problem with auto_increment in partitioned innodb tables. (in ha_partition::write_row over partitions file->ha_write_row) Solution is to use the patch for bug#33479, which refines the usage of mutexes for auto_increment. Backport of bug-33479 from 6.0: Bug-33479: auto_increment failures in partitioning Several problems with auto_increment in partitioning (with MyISAM, InnoDB. Locking issues, not handling multi-row INSERTs properly etc.) Changed the auto_increment handling for partitioning: Added a ha_data variable in table_share for storage engine specific data such as auto_increment value handling in partitioning, also see WL 4305 and using the ha_data->mutex to lock around read + update. The idea is this: Store the table's reserved auto_increment value in the TABLE_SHARE and use a mutex to, lock it for reading and updating it and unlocking it, in one block. Only accessing all partitions when it is not initialized. Also allow reservations of ranges, and if no one has done a reservation afterwards, lower the reservation to what was actually used after the statement is done (via release_auto_increment from WL 3146). The lock is kept from the first reservation if it is statement based replication and a multi-row INSERT statement where the number of candidate rows to insert is not known in advance (like INSERT SELECT, LOAD DATA, unlike INSERT VALUES (row1), (row2),,(rowN)). This should also lead to better concurrancy (no need to have a mutex protection around write_row in all cases) and work with any local storage engine. mysql-test/suite/parts/inc/partition_auto_increment.inc: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning Test source file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_archive.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_blackhole.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_innodb.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_memory.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_myisam.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/r/partition_auto_increment_ndb.result: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning result file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_archive.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_blackhole.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_innodb.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_memory.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_myisam.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment mysql-test/suite/parts/t/partition_auto_increment_ndb.test: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning test file for testing auto_increment sql/ha_partition.cc: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: Failures using auto_increment and partitioning Changed ha_partition::get_auto_increment from file->get_auto_increment to file->info(HA_AUTO_STATUS), since it is works better with InnoDB (InnoDB can have issues with partitioning and auto_increment, where get_auto_increment sometimes can return a non updated value.) Using the new table_share->ha_data for keeping the auto_increment value, shared by all instances of the same table. It is read+updated when holding a auto_increment specific mutex. Also added release_auto_increment to decrease gaps if possible. And a lock for multi-row INSERT statements where the number of candidate rows to insert is not known in advance (like INSERT SELECT, LOAD DATA; Unlike INSERT INTO (row1),(row2),,(rowN)). Fixed a small bug, copied++ to (*copied)++ and the same for deleted. Changed from current_thd, to ha_thd() sql/ha_partition.h: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: Failures using auto_increment and partitioning Added a new struct HA_DATA_PARTITION to be used in table_share->ha_data Added a private function to set auto_increment values if needed Removed the restore_auto_increment (the hander version is better) Added lock/unlock functions for auto_increment handling. Changed copied/deleted to const. sql/handler.h: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: auto_increment failures in partitioning Added const for changed_partitions Added comments about SQLCOM_TRUNCATE for delete_all_rows sql/table.h: Bug#38804: Query deadlock causes all tables to be inaccessible. Backporting from 6.0 of: Bug-33479: Failures using auto_increment and partitioning Added a variable in table_share: ha_data for storage of storage engine specific data (such as auto_increment handling in partitioning). --- sql/ha_partition.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 97f5624608f..908248e1dda 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -37,6 +37,15 @@ typedef struct st_partition_share } PARTITION_SHARE; #endif +/** + Partition specific ha_data struct. + @todo: move all partition specific data from TABLE_SHARE here. +*/ +typedef struct st_ha_data_partition +{ + ulonglong next_auto_inc_val; /**< first non reserved value */ + bool auto_inc_initialized; +} HA_DATA_PARTITION; #define PARTITION_BYTES_IN_POS 2 class ha_partition :public handler @@ -141,6 +150,12 @@ private: "own" the m_part_info structure. */ bool is_clone; + bool auto_increment_lock; /**< lock reading/updating auto_inc */ + /** + Flag to keep the auto_increment lock through out the statement. + This to ensure it will work with statement based replication. + */ + bool auto_increment_safe_stmt_log_lock; public: handler *clone(MEM_ROOT *mem_root); virtual void set_part_info(partition_info *part_info) @@ -197,8 +212,8 @@ public: virtual char *update_table_comment(const char *comment); virtual int change_partitions(HA_CREATE_INFO *create_info, const char *path, - ulonglong *copied, - ulonglong *deleted, + ulonglong * const copied, + ulonglong * const deleted, const uchar *pack_frm_data, size_t pack_frm_len); virtual int drop_partitions(const char *path); @@ -212,7 +227,7 @@ public: virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share); private: int prepare_for_rename(); - int copy_partitions(ulonglong *copied, ulonglong *deleted); + int copy_partitions(ulonglong * const copied, ulonglong * const deleted); void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, handler *file, const char *part_name, @@ -829,12 +844,51 @@ public: auto_increment_column_changed ------------------------------------------------------------------------- */ - virtual void restore_auto_increment(ulonglong prev_insert_id); virtual void get_auto_increment(ulonglong offset, ulonglong increment, ulonglong nb_desired_values, ulonglong *first_value, ulonglong *nb_reserved_values); virtual void release_auto_increment(); +private: + virtual int reset_auto_increment(ulonglong value); + virtual void lock_auto_increment() + { + /* lock already taken */ + if (auto_increment_safe_stmt_log_lock) + return; + DBUG_ASSERT(table_share->ha_data && !auto_increment_lock); + if(table_share->tmp_table == NO_TMP_TABLE) + { + auto_increment_lock= TRUE; + pthread_mutex_lock(&table_share->mutex); + } + } + virtual void unlock_auto_increment() + { + DBUG_ASSERT(table_share->ha_data); + /* + If auto_increment_safe_stmt_log_lock is true, we have to keep the lock. + It will be set to false and thus unlocked at the end of the statement by + ha_partition::release_auto_increment. + */ + if(auto_increment_lock && !auto_increment_safe_stmt_log_lock) + { + pthread_mutex_unlock(&table_share->mutex); + auto_increment_lock= FALSE; + } + } + virtual void set_auto_increment_if_higher(const ulonglong nr) + { + HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data; + lock_auto_increment(); + /* must check when the mutex is taken */ + if (nr >= ha_data->next_auto_inc_val) + ha_data->next_auto_inc_val= nr + 1; + ha_data->auto_inc_initialized= TRUE; + unlock_auto_increment(); + } + +public: /* ------------------------------------------------------------------------- -- cgit v1.2.1 From 3e1d88d188b13a9b7ad2e40b5fee264d44c618e2 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 18 Sep 2008 22:49:34 +0300 Subject: Bug#30573: Ordered range scan over partitioned tables returns some rows twice and Bug#33555: Group By Query does not correctly aggregate partitions Backport of bug-33257 which is the same bug. read_range_*() calls was not passed to the partition handlers, but was translated to index_read/next family calls. Resulting in duplicates rows and wrong aggregations. mysql-test/r/partition_range.result: Bug#30573: Ordered range scan over partitioned tables returns some rows twice Updated result file mysql-test/t/partition_range.test: Bug#30573: Ordered range scan over partitioned tables returns some rows twice Re-enabled the test sql/ha_partition.cc: Bug#30573: Ordered range scan over partitioned tables returns some rows twice backport of bug-33257, correct handling of read_range_* calls, without converting them to index_read/next calls sql/ha_partition.h: Bug#30573: Ordered range scan over partitioned tables returns some rows twice backport of bug-33257, correct handling of read_range_* calls, without converting them to index_read/next calls --- sql/ha_partition.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 97f5624608f..459b566b6d8 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -49,7 +49,8 @@ private: partition_index_first_unordered= 2, partition_index_last= 3, partition_index_read_last= 4, - partition_no_index_scan= 5 + partition_read_range = 5, + partition_no_index_scan= 6 }; /* Data for the partition handler */ int m_mode; // Open mode @@ -63,8 +64,6 @@ private: handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors partition_info *m_part_info; // local reference to partition - uchar *m_start_key_ref; // Reference of start key in current - // index scan info Field **m_part_field_array; // Part field array locally to save acc uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan KEY *m_curr_key_info; // Current index @@ -429,9 +428,7 @@ public: virtual int read_range_next(); private: - int common_index_read(uchar * buf, const uchar * key, - key_part_map keypart_map, - enum ha_rkey_function find_flag); + int common_index_read(uchar * buf, bool have_start_key); int common_first_last(uchar * buf); int partition_scan_set_up(uchar * buf, bool idx_read_flag); int handle_unordered_next(uchar * buf, bool next_same); -- cgit v1.2.1 From 65811a336dbde9d09b6ed0b470fa37bd488a7a74 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Sun, 5 Oct 2008 00:40:30 +0200 Subject: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table The fast/on-line add/drop index handler calls was not implemented whithin the partitioning. This implements it in the partitioning handler. Since this is only used by the not included InnoDB plugin, there is no test case. (Have tested it manually with the plugin, and it does not allow unique indexes not including partitioning function, or removal of pk, which in innodb generates a new pk, which is not in the partitioning function.) NOTE: This introduces a new handler method, and because of that changes the storage engine api. (One cannot use a handlerton to see the capabilities of a table's handler if it is partitioned. So I added a wrapper function in the handler that defaults to the handlerton function, which the partitioning handler overrides. sql/ha_partition.cc: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table Added support for fast/on-line add/drop index. Implemented alter_table_flags as bit-or of the partitioned hton and the first partitions alter_table_flags. It is only to forward the calls for the other functions: check_if_incompatible_data add_index prepare_drop_index final_drop_index to all parts handler sql/ha_partition.h: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table Added support for fast/on-line add/drop index. sql/handler.h: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table Added the function on handler level, defaulting to use the handlerton function, but a handler can override it. Needed for partitioned tables. NOTE: Change of storage engine api. sql/sql_partition.cc: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table Using the new handler function, instead of the handlerton function. This works better with the partitioning handler. sql/sql_table.cc: Bug#37453: Dropping/creating index on partitioned table with InnoDB Plugin locks table Using the new handler function, instead of the handlerton function. This works better with the partitioning handler. Also using new process info for 'manage keys' (kind of fix for bug-37550). --- sql/ha_partition.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 97f5624608f..4e4b746d611 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -210,6 +210,8 @@ public: DBUG_RETURN(0); } virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share); + virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info, + uint table_changes); private: int prepare_for_rename(); int copy_partitions(ulonglong *copied, ulonglong *deleted); @@ -762,6 +764,11 @@ public: return m_file[0]->index_flags(inx, part, all_parts); } + /** + wrapper function for handlerton alter_table_flags, since + the ha_partition_hton cannot know all its capabilities + */ + virtual uint alter_table_flags(uint flags); /* extensions of table handler files */ @@ -898,13 +905,14 @@ public: ------------------------------------------------------------------------- MODULE on-line ALTER TABLE ------------------------------------------------------------------------- - These methods are in the handler interface but never used (yet) - They are to be used by on-line alter table add/drop index: + These methods are in the handler interface. (used by innodb-plugin) + They are used for on-line/fast alter table add/drop index: ------------------------------------------------------------------------- - virtual ulong index_ddl_flags(KEY *wanted_index) const - virtual int add_index(TABLE *table_arg,KEY *key_info,uint num_of_keys); - virtual int drop_index(TABLE *table_arg,uint *key_num,uint num_of_keys); */ + virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys); + virtual int prepare_drop_index(TABLE *table_arg, uint *key_num, + uint num_of_keys); + virtual int final_drop_index(TABLE *table_arg); /* ------------------------------------------------------------------------- -- cgit v1.2.1 From d3ea7430152fad48cabd9efb8c80d177405dd090 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 10 Oct 2008 12:01:01 +0200 Subject: Bug#37721: ORDER BY when WHERE contains non-partitioned index column There was actually two problems 1) when clustered pk, order by non pk index should also compare with pk as last resort to differ keys from each other 2) bug in the index search handling in ha_partition (was found when extending the test case Solution to 1 was to include the pk in key compare if clustered pk and search on other index. Solution for 2 was to remove the optimization from ordered scan to unordered scan if clustered pk. mysql-test/r/partition_innodb.result: Bug#37721: ORDER BY when WHERE contains non-partitioned index column updated test result. mysql-test/t/partition_innodb.test: Bug#37721: ORDER BY when WHERE contains non-partitioned index column Added test case for bug verification. sql/ha_partition.cc: Bug#37721: ORDER BY when WHERE contains non-partitioned index column using m_curr_key_info with both given index and PK if clustered PK. Also including PK in read_set. Added debug prints for easier verification. sql/ha_partition.h: Bug#37721: ORDER BY when WHERE contains non-partitioned index column Changed m_curr_key_info to a null terminated array with max 2 keys and a terminating null. For use with key_rec_cmp with both given index and PK. sql/key.cc: Bug#37721: ORDER BY when WHERE contains non-partitioned index column added handling of a null terminated array of keys for use in compare. --- sql/ha_partition.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 685f057dfce..6e52106dfa5 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -74,9 +74,16 @@ private: handler **m_added_file; // Added parts kept for errors partition_info *m_part_info; // local reference to partition Field **m_part_field_array; // Part field array locally to save acc - uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan - KEY *m_curr_key_info; // Current index - uchar *m_rec0; // table->record[0] + uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan + /* + Current index. + When used in key_rec_cmp: If clustered pk, index compare + must compare pk if given index is same for two rows. + So normally m_curr_key_info[0]= current index and m_curr_key[1]= NULL, + and if clustered pk, [0]= current index, [1]= pk, [2]= NULL + */ + KEY *m_curr_key_info[3]; // Current index + uchar *m_rec0; // table->record[0] QUEUE m_queue; // Prio queue used by sorted read /* Since the partition handler is a handler on top of other handlers, it -- cgit v1.2.1 From c6115db4c3a693dfed25e8e60e8ff5d06ba72756 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 10 Oct 2008 20:12:38 +0200 Subject: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Problem was that partitioning specific commands was accepted for non partitioned tables and treated like ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE, after bug-20129 was fixed, which changed the code path from mysql_alter_table to mysql_admin_table. Solution was to check if the table was partitioned before trying to execute the admin command mysql-test/r/partition_mgm_err.result: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Updated test result mysql-test/t/partition_mgm_err.test: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Updated test case sql/ha_partition.cc: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. sql/ha_partition.h: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. sql/sql_lex.h: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. Removed ALTER_ANALYZE/CHECK/OPTIMIZE/REPAIR_PARTITION and added ALTER_ADMIN_PARTITION instead. sql/sql_partition.cc: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. Removed ALTER_ANALYZE/CHECK/OPTIMIZE/REPAIR_PARTITION and added ALTER_ADMIN_PARTITION instead. sql/sql_table.cc: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Give error and return if trying partitioning admin command on non partitioned table. Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. Removed ALTER_ANALYZE/CHECK/OPTIMIZE/REPAIR_PARTITION and added ALTER_ADMIN_PARTITION instead. sql/sql_yacc.yy: Bug#39434: ALTER TABLE CHECK/OPTIMIZE/ANALYZE PARTITION work on non-partitioned table Simplified the code by using ALTER_ADMIN_PARTITION for all commands that go through mysql_admin_tables and is set for partitioning specific commands that. Removed ALTER_ANALYZE/CHECK/OPTIMIZE/REPAIR_PARTITION and added ALTER_ADMIN_PARTITION instead. --- sql/ha_partition.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 685f057dfce..d36e993d399 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -988,8 +988,7 @@ public: virtual bool is_crashed() const; private: - int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, - uint flags, bool all_parts); + int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, uint flags); public: /* ------------------------------------------------------------------------- -- cgit v1.2.1 From 620d955e3ae9dbe6820b18668947805efd6547ec Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 23 Oct 2008 22:14:07 +0200 Subject: Bug#40176: update as first partitioning statement breaks auto increment The auto_increment value was not initialized if the first statement after opening a table was an 'UPDATE'. solution was to check initialize if it was not, before trying to increase it in update. mysql-test/suite/parts/inc/partition_auto_increment.inc: Bug#40176: update as first partitioning statement breaks auto increment Added tests for verifying the bug and show some more auto_increment flaws mysql-test/suite/parts/r/partition_auto_increment_archive.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests mysql-test/suite/parts/r/partition_auto_increment_blackhole.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests mysql-test/suite/parts/r/partition_auto_increment_innodb.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests mysql-test/suite/parts/r/partition_auto_increment_memory.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests mysql-test/suite/parts/r/partition_auto_increment_myisam.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests mysql-test/suite/parts/r/partition_auto_increment_ndb.result: Bug#40176: update as first partitioning statement breaks auto increment Updated test results, due to added tests sql/ha_partition.cc: Bug#40176: update as first partitioning statement breaks auto increment make sure that the auto_increment value is initialized before updating it. (missed initializing in mysql_update_row). sql/ha_partition.h: Bug#40176: update as first partitioning statement breaks auto increment Assert that it is initialized, before updating the auto_increment value --- sql/ha_partition.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 685f057dfce..31e5169ac7f 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -878,10 +878,10 @@ private: { HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data; lock_auto_increment(); + DBUG_ASSERT(ha_data->auto_inc_initialized == TRUE); /* must check when the mutex is taken */ if (nr >= ha_data->next_auto_inc_val) ha_data->next_auto_inc_val= nr + 1; - ha_data->auto_inc_initialized= TRUE; unlock_auto_increment(); } -- cgit v1.2.1 From b72d1507db95326119afdcb4764fa457a7f888b7 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 29 Oct 2008 21:20:04 +0100 Subject: Bug#39084: Getting intermittent errors with statement-based binary logging Problem was that partitioning cached the table flags. These flags could change due to TRANSACTION LEVEL changes. Solution was to remove the cache and always return the table flags from the first partition (if the handler was initialized). mysql-test/r/partition_innodb_stmt.result: Bug#39084: Getting intermittent errors with statement-based binary logging New test result file. mysql-test/t/partition_innodb_stmt.test: Bug#39084: Getting intermittent errors with statement-based binary logging New test file. sql/ha_partition.cc: Bug#39084: Getting intermittent errors with statement-based binary logging Removed m_table_flags, and added m_handler_status. Added checks that all partitions have the same table flags. Moved some variable initializations. Updated some comments. Fixed typo initialise -> initialize Changed HA_EXTTA_NO_READCHECK to do nothing, since it is only used in ha_open, which is called for every partition in ::open anyway. sql/ha_partition.h: Bug#39084: Getting intermittent errors with statement-based binary logging Removed m_table_flags, and added m_handler_status. Always return the first partitions table flags, instead of using cached table flags. Added define of enabled/disabled partitioning table flags Fixed type initialise -> initialize Updated some comments. sql/handler.cc: Bug#39084: Getting intermittent errors with statement-based binary logging Fixed type initialise -> initialize. sql/handler.h: Bug#39084: Getting intermittent errors with statement-based binary logging Added comment to understand where the cached value is set. --- sql/ha_partition.h | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'sql/ha_partition.h') diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 685f057dfce..2cb1e83de91 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -48,6 +48,13 @@ typedef struct st_ha_data_partition } HA_DATA_PARTITION; #define PARTITION_BYTES_IN_POS 2 +#define PARTITION_ENABLED_TABLE_FLAGS (HA_FILE_BASED | HA_REC_NOT_IN_SEQ) +#define PARTITION_DISABLED_TABLE_FLAGS (HA_CAN_GEOMETRY | \ + HA_CAN_FULLTEXT | \ + HA_DUPLICATE_POS | \ + HA_CAN_SQL_HANDLER | \ + HA_CAN_INSERT_DELAYED | \ + HA_PRIMARY_KEY_REQUIRED_FOR_POSITION) class ha_partition :public handler { private: @@ -85,8 +92,15 @@ private: for this since the MySQL Server sometimes allocating the handler object without freeing them. */ - longlong m_table_flags; ulong m_low_byte_first; + enum enum_handler_status + { + handler_not_initialized= 0, + handler_initialized, + handler_opened, + handler_closed + }; + enum_handler_status m_handler_status; uint m_reorged_parts; // Number of reorganised parts uint m_tot_parts; // Total number of partitions; @@ -182,7 +196,7 @@ public: enable later calls of the methods to retrieve constants from the under- lying handlers. Returns false if not successful. */ - bool initialise_partition(MEM_ROOT *mem_root); + bool initialize_partition(MEM_ROOT *mem_root); /* ------------------------------------------------------------------------- @@ -585,6 +599,8 @@ public: The partition handler will support whatever the underlying handlers support except when specifically mentioned below about exceptions to this rule. + NOTE: This cannot be cached since it can depend on TRANSACTION ISOLATION + LEVEL which is dynamic, see bug#39084. HA_READ_RND_SAME: Not currently used. (Means that the handler supports the rnd_same() call) @@ -709,9 +725,33 @@ public: transfer those calls into index_read and other calls in the index scan module. (NDB) + + HA_PRIMARY_KEY_REQUIRED_FOR_POSITION: + Does the storage engine need a PK for position? + Used with hidden primary key in InnoDB. + Hidden primary keys cannot be supported by partitioning, since the + partitioning expressions columns must be a part of the primary key. + (InnoDB) + + HA_FILE_BASED is always set for partition handler since we use a + special file for handling names of partitions, engine types. + HA_REC_NOT_IN_SEQ is always set for partition handler since we cannot + guarantee that the records will be returned in sequence. + HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_CAN_SQL_HANDLER, HA_DUPLICATE_POS, + HA_CAN_INSERT_DELAYED, HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is disabled + until further investigated. */ - virtual ulonglong table_flags() const - { return m_table_flags; } + virtual Table_flags table_flags() const + { + DBUG_ENTER("ha_partition::table_flags"); + if (m_handler_status < handler_initialized || + m_handler_status >= handler_closed) + DBUG_RETURN(PARTITION_ENABLED_TABLE_FLAGS); + else + DBUG_RETURN((m_file[0]->ha_table_flags() & + ~(PARTITION_DISABLED_TABLE_FLAGS)) | + (PARTITION_ENABLED_TABLE_FLAGS)); + } /* This is a bitmap of flags that says how the storage engine @@ -889,7 +929,7 @@ public: /* ------------------------------------------------------------------------- - MODULE initialise handler for HANDLER call + MODULE initialize handler for HANDLER call ------------------------------------------------------------------------- This method is a special InnoDB method called before a HANDLER query. ------------------------------------------------------------------------- -- cgit v1.2.1