Loading Docs/manual.texi +16 −5 Original line number Diff line number Diff line Loading @@ -17896,6 +17896,11 @@ tables as one. This only works with MERGE tables. @xref{MERGE}. For the moment you need to have @code{SELECT}, @code{UPDATE}, and @code{DELETE} privileges on the tables you map to a @code{MERGE} table. All mapped tables must be in the same database as the @code{MERGE} table. @item In the created table the @code{PRIMARY} key will be placed first, followed by all @code{UNIQUE} keys and then the normal keys. This helps the @strong{MySQL} optimizer to prioritize which key to use and also more quickly detect duplicated @code{UNIQUE} keys. @end itemize @cindex silent column changes Loading Loading @@ -22597,7 +22602,7 @@ You may also want to change @code{binlog_cache_size} and @itemize @bullet @item @strong{MySQL} requires a @code{PRIMARY KEY} in each BDB table to be able to refer to previously read rows. If you don't create on, able to refer to previously read rows. If you don't create one, @strong{MySQL} will create an maintain a hidden @code{PRIMARY KEY} for you. The hidden key has a length of 5 bytes and is incremented for each insert attempt. Loading @@ -22617,8 +22622,6 @@ you don't use @code{LOCK TABLE}, @strong{MYSQL} will issue an internal multiple-write lock on the table to ensure that the table will be properly locked if another thread issues a table lock. @item @code{ALTER TABLE} doesn't yet work on @code{BDB} tables. @item Internal locking in @code{BDB} tables is done on page level. @item @code{SELECT COUNT(*) FROM table_name} is slow as @code{BDB} tables doesn't Loading @@ -22636,8 +22639,8 @@ tables. In other words, the key information will take a little more space in @code{BDB} tables compared to MyISAM tables which don't use @code{PACK_KEYS=0}. @item There is often holes in the BDB table to allow you to insert new rows between different keys. This makes BDB tables somewhat larger than There is often holes in the BDB table to allow you to insert new rows in the middle of the key tree. This makes BDB tables somewhat larger than MyISAM tables. @item @strong{MySQL} performs a checkpoint each time a new Berkeley DB log Loading Loading @@ -39636,6 +39639,14 @@ though, so Version 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.29 @itemize @bullet @item When creating a table, put @code{PRIMARY} keys first, followed by @code{UNIQUE} keys. @item Fixed a bug in @code{UPDATE} involving multi-part keys where one specified all key parts both in the update and the @code{WHERE} part. In this case @strong{MySQL} could try to update a record that didn't match the whole @code{WHERE} part. @item Changed drop table to first drop the tables and then the @code{.frm} file. @item Fixed a bug in the hostname cache which caused @code{mysqld} to report the sql/ha_berkeley.cc +30 −19 Original line number Diff line number Diff line Loading @@ -1660,7 +1660,8 @@ longlong ha_berkeley::get_auto_increment() } else { DBT row; DBT row,old_key; DBC *auto_cursor; bzero((char*) &row,sizeof(row)); uint key_len; KEY *key_info= &table->key_info[active_index]; Loading @@ -1670,25 +1671,35 @@ longlong ha_berkeley::get_auto_increment() key_buff, table->record[0], table->next_number_key_offset); /* Store for compare */ memcpy(key_buff2, key_buff, (key_len=last_key.size)); memcpy(old_key.data=key_buff2, key_buff, (old_key.size=last_key.size)); error=1; if (!(file->cursor(key_file[active_index], transaction, &auto_cursor, 0))) { /* Modify the compare so that we will find the next key */ key_info->handler.bdb_return_if_eq= 1; /* We lock the next key as the new key will probl. be on the same page */ error=cursor->c_get(cursor, &last_key, &row, DB_SET_RANGE | DB_RMW), error=auto_cursor->c_get(auto_cursor, &last_key, &row, DB_SET_RANGE | DB_RMW); key_info->handler.bdb_return_if_eq= 0; if (!error || error == DB_NOTFOUND) { /* Now search go one step back and then we should have found the biggest key with the given prefix */ if (read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV | DB_RMW), table->record[1], active_index, &row, (DBT*) 0, 0) || berkeley_key_cmp(table, key_info, key_buff2, key_len)) error=1; // Something went wrong or no such key error=1; if (!auto_cursor->c_get(auto_cursor, &last_key, &row, DB_PREV | DB_RMW) && !berkeley_cmp_packed_key(key_file[active_index], &old_key, &last_key)) { error=0; // Found value unpack_key(table->record[1], &last_key, active_index); } } auto_cursor->c_close(auto_cursor); } } if (!error) nr=(longlong) table->next_number_field->val_int_offset(table->rec_buff_length)+1; ha_berkeley::index_end(); Loading sql/sql_table.cc +42 −20 Original line number Diff line number Diff line Loading @@ -327,18 +327,28 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } /* Create keys */ List_iterator<Key> key_iterator(keys); uint key_parts=0,key_count=keys.elements; bool primary_key=0,unique_key=0; List<Key> keys_in_order; // Add new keys here Key *primary_key=0; bool unique_key=0; Key *key; uint tmp; tmp=min(file->max_keys(), MAX_KEY); if (key_count > tmp) { my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); DBUG_RETURN(-1); } /* Check keys; Put PRIMARY KEY first, then UNIQUE keys and other keys last This will make checking for duplicated keys faster and ensure that primary keys are prioritized. */ while ((key=key_iterator++)) { tmp=max(file->max_key_parts(),MAX_REF_PARTS); Loading @@ -353,17 +363,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } key_parts+=key->columns.elements; } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!key_info_buffer || ! key_part_info) DBUG_RETURN(-1); // Out of memory key_iterator.rewind(); for (; (key=key_iterator++) ; key_info++) { uint key_length=0; key_part_spec *column; if (key->type == Key::PRIMARY) { if (primary_key) Loading @@ -371,10 +370,39 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); DBUG_RETURN(-1); } primary_key=1; primary_key=key; } else if (key->type == Key::UNIQUE) { unique_key=1; if (keys_in_order.push_front(key)) DBUG_RETURN(-1); } else if (keys_in_order.push_back(key)) DBUG_RETURN(-1); } if (primary_key) { if (keys_in_order.push_front(primary_key)) DBUG_RETURN(-1); } else if (!unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) { my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); DBUG_RETURN(-1); } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!key_info_buffer || ! key_part_info) DBUG_RETURN(-1); // Out of memory List_iterator<Key> key_iterator_in_order(keys_in_order); for (; (key=key_iterator_in_order++) ; key_info++) { uint key_length=0; key_part_spec *column; key_info->flags= (key->type == Key::MULTIPLE) ? 0 : (key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME; key_info->key_parts=(uint8) key->columns.elements; Loading Loading @@ -508,12 +536,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, my_error(ER_WRONG_AUTO_KEY,MYF(0)); DBUG_RETURN(-1); } if (!primary_key && !unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) { my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); DBUG_RETURN(-1); } /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) Loading sql/sql_update.cc +10 −1 Original line number Diff line number Diff line Loading @@ -75,8 +75,16 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, if (table->timestamp_field && // Don't set timestamp if used table->timestamp_field->query_id == thd->query_id) table->time_stamp=0; /* Reset the query_id string so that ->used_keys is based on the WHERE */ table->used_keys=table->keys_in_use; table->quick_keys=0; reg2 Item *item; List_iterator<Item> it(fields); ulong query_id=thd->query_id-1; while ((item=it++)) ((Item_field*) item)->field->query_id=query_id; if (setup_fields(thd,table_list,values,0,0) || setup_conds(thd,table_list,&conds)) { Loading @@ -84,7 +92,8 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, DBUG_RETURN(-1); /* purecov: inspected */ } old_used_keys=table->used_keys; table->used_keys=0; // Can't use 'only index' // Don't count on usage of 'only index' when calculating which key to use table->used_keys=0; select=make_select(table,0,0,conds,&error); if (error || (select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES), Loading Loading
Docs/manual.texi +16 −5 Original line number Diff line number Diff line Loading @@ -17896,6 +17896,11 @@ tables as one. This only works with MERGE tables. @xref{MERGE}. For the moment you need to have @code{SELECT}, @code{UPDATE}, and @code{DELETE} privileges on the tables you map to a @code{MERGE} table. All mapped tables must be in the same database as the @code{MERGE} table. @item In the created table the @code{PRIMARY} key will be placed first, followed by all @code{UNIQUE} keys and then the normal keys. This helps the @strong{MySQL} optimizer to prioritize which key to use and also more quickly detect duplicated @code{UNIQUE} keys. @end itemize @cindex silent column changes Loading Loading @@ -22597,7 +22602,7 @@ You may also want to change @code{binlog_cache_size} and @itemize @bullet @item @strong{MySQL} requires a @code{PRIMARY KEY} in each BDB table to be able to refer to previously read rows. If you don't create on, able to refer to previously read rows. If you don't create one, @strong{MySQL} will create an maintain a hidden @code{PRIMARY KEY} for you. The hidden key has a length of 5 bytes and is incremented for each insert attempt. Loading @@ -22617,8 +22622,6 @@ you don't use @code{LOCK TABLE}, @strong{MYSQL} will issue an internal multiple-write lock on the table to ensure that the table will be properly locked if another thread issues a table lock. @item @code{ALTER TABLE} doesn't yet work on @code{BDB} tables. @item Internal locking in @code{BDB} tables is done on page level. @item @code{SELECT COUNT(*) FROM table_name} is slow as @code{BDB} tables doesn't Loading @@ -22636,8 +22639,8 @@ tables. In other words, the key information will take a little more space in @code{BDB} tables compared to MyISAM tables which don't use @code{PACK_KEYS=0}. @item There is often holes in the BDB table to allow you to insert new rows between different keys. This makes BDB tables somewhat larger than There is often holes in the BDB table to allow you to insert new rows in the middle of the key tree. This makes BDB tables somewhat larger than MyISAM tables. @item @strong{MySQL} performs a checkpoint each time a new Berkeley DB log Loading Loading @@ -39636,6 +39639,14 @@ though, so Version 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.29 @itemize @bullet @item When creating a table, put @code{PRIMARY} keys first, followed by @code{UNIQUE} keys. @item Fixed a bug in @code{UPDATE} involving multi-part keys where one specified all key parts both in the update and the @code{WHERE} part. In this case @strong{MySQL} could try to update a record that didn't match the whole @code{WHERE} part. @item Changed drop table to first drop the tables and then the @code{.frm} file. @item Fixed a bug in the hostname cache which caused @code{mysqld} to report the
sql/ha_berkeley.cc +30 −19 Original line number Diff line number Diff line Loading @@ -1660,7 +1660,8 @@ longlong ha_berkeley::get_auto_increment() } else { DBT row; DBT row,old_key; DBC *auto_cursor; bzero((char*) &row,sizeof(row)); uint key_len; KEY *key_info= &table->key_info[active_index]; Loading @@ -1670,25 +1671,35 @@ longlong ha_berkeley::get_auto_increment() key_buff, table->record[0], table->next_number_key_offset); /* Store for compare */ memcpy(key_buff2, key_buff, (key_len=last_key.size)); memcpy(old_key.data=key_buff2, key_buff, (old_key.size=last_key.size)); error=1; if (!(file->cursor(key_file[active_index], transaction, &auto_cursor, 0))) { /* Modify the compare so that we will find the next key */ key_info->handler.bdb_return_if_eq= 1; /* We lock the next key as the new key will probl. be on the same page */ error=cursor->c_get(cursor, &last_key, &row, DB_SET_RANGE | DB_RMW), error=auto_cursor->c_get(auto_cursor, &last_key, &row, DB_SET_RANGE | DB_RMW); key_info->handler.bdb_return_if_eq= 0; if (!error || error == DB_NOTFOUND) { /* Now search go one step back and then we should have found the biggest key with the given prefix */ if (read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV | DB_RMW), table->record[1], active_index, &row, (DBT*) 0, 0) || berkeley_key_cmp(table, key_info, key_buff2, key_len)) error=1; // Something went wrong or no such key error=1; if (!auto_cursor->c_get(auto_cursor, &last_key, &row, DB_PREV | DB_RMW) && !berkeley_cmp_packed_key(key_file[active_index], &old_key, &last_key)) { error=0; // Found value unpack_key(table->record[1], &last_key, active_index); } } auto_cursor->c_close(auto_cursor); } } if (!error) nr=(longlong) table->next_number_field->val_int_offset(table->rec_buff_length)+1; ha_berkeley::index_end(); Loading
sql/sql_table.cc +42 −20 Original line number Diff line number Diff line Loading @@ -327,18 +327,28 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } /* Create keys */ List_iterator<Key> key_iterator(keys); uint key_parts=0,key_count=keys.elements; bool primary_key=0,unique_key=0; List<Key> keys_in_order; // Add new keys here Key *primary_key=0; bool unique_key=0; Key *key; uint tmp; tmp=min(file->max_keys(), MAX_KEY); if (key_count > tmp) { my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); DBUG_RETURN(-1); } /* Check keys; Put PRIMARY KEY first, then UNIQUE keys and other keys last This will make checking for duplicated keys faster and ensure that primary keys are prioritized. */ while ((key=key_iterator++)) { tmp=max(file->max_key_parts(),MAX_REF_PARTS); Loading @@ -353,17 +363,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } key_parts+=key->columns.elements; } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!key_info_buffer || ! key_part_info) DBUG_RETURN(-1); // Out of memory key_iterator.rewind(); for (; (key=key_iterator++) ; key_info++) { uint key_length=0; key_part_spec *column; if (key->type == Key::PRIMARY) { if (primary_key) Loading @@ -371,10 +370,39 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); DBUG_RETURN(-1); } primary_key=1; primary_key=key; } else if (key->type == Key::UNIQUE) { unique_key=1; if (keys_in_order.push_front(key)) DBUG_RETURN(-1); } else if (keys_in_order.push_back(key)) DBUG_RETURN(-1); } if (primary_key) { if (keys_in_order.push_front(primary_key)) DBUG_RETURN(-1); } else if (!unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) { my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); DBUG_RETURN(-1); } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!key_info_buffer || ! key_part_info) DBUG_RETURN(-1); // Out of memory List_iterator<Key> key_iterator_in_order(keys_in_order); for (; (key=key_iterator_in_order++) ; key_info++) { uint key_length=0; key_part_spec *column; key_info->flags= (key->type == Key::MULTIPLE) ? 0 : (key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME; key_info->key_parts=(uint8) key->columns.elements; Loading Loading @@ -508,12 +536,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, my_error(ER_WRONG_AUTO_KEY,MYF(0)); DBUG_RETURN(-1); } if (!primary_key && !unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) { my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); DBUG_RETURN(-1); } /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) Loading
sql/sql_update.cc +10 −1 Original line number Diff line number Diff line Loading @@ -75,8 +75,16 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, if (table->timestamp_field && // Don't set timestamp if used table->timestamp_field->query_id == thd->query_id) table->time_stamp=0; /* Reset the query_id string so that ->used_keys is based on the WHERE */ table->used_keys=table->keys_in_use; table->quick_keys=0; reg2 Item *item; List_iterator<Item> it(fields); ulong query_id=thd->query_id-1; while ((item=it++)) ((Item_field*) item)->field->query_id=query_id; if (setup_fields(thd,table_list,values,0,0) || setup_conds(thd,table_list,&conds)) { Loading @@ -84,7 +92,8 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, DBUG_RETURN(-1); /* purecov: inspected */ } old_used_keys=table->used_keys; table->used_keys=0; // Can't use 'only index' // Don't count on usage of 'only index' when calculating which key to use table->used_keys=0; select=make_select(table,0,0,conds,&error); if (error || (select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES), Loading