2394
2400
goto err_handler;
2403
Use table_share->ha_data to share auto_increment_value among all handlers
2406
if (is_not_tmp_table)
2407
pthread_mutex_lock(&table_share->LOCK_ha_data);
2408
if (!table_share->ha_data)
2410
HA_DATA_PARTITION *ha_data;
2411
/* currently only needed for auto_increment */
2412
table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
2413
alloc_root(&table_share->mem_root,
2414
sizeof(HA_DATA_PARTITION));
2417
DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
2418
bzero(ha_data, sizeof(HA_DATA_PARTITION));
2420
if (is_not_tmp_table)
2421
pthread_mutex_unlock(&table_share->LOCK_ha_data);
2397
2423
Some handlers update statistics as part of the open call. This will in
2398
2424
some cases corrupt the statistics of the partition handler and thus
2399
2425
to ensure we have correct statistics we call info from open after
2751
2780
If we have an auto_increment column and we are writing a changed row
2752
2781
or a new row, then update the auto_increment value in the record.
2754
if (table->next_number_field && buf == table->record[0])
2783
if (have_auto_increment)
2757
Some engines (InnoDB for example) can change autoincrement
2758
counter only after 'table->write_row' operation.
2759
So if another thread gets inside the ha_partition::write_row
2760
before it is complete, it gets same auto_increment value,
2761
which means DUP_KEY error (bug #27405)
2762
Here we separate the access using table_share->mutex, and
2763
use autoincrement_lock variable to avoid unnecessary locks.
2764
Probably not an ideal solution.
2766
if (table_share->tmp_table == NO_TMP_TABLE && m_innodb)
2785
if (!ha_data->auto_inc_initialized &&
2786
!table->s->next_number_keypart)
2769
Bug#30878 crash when alter table from non partitioned table
2771
Checking if tmp table then there is no need to lock,
2772
and the table_share->mutex may not be initialised.
2789
If auto_increment in table_share is not initialized, start by
2774
autoincrement_lock= TRUE;
2775
pthread_mutex_lock(&table_share->mutex);
2792
info(HA_STATUS_AUTO);
2777
2794
error= update_auto_increment();
2780
2796
If we have failed to set the auto-increment value for this row,
2781
2797
it is highly likely that we will not be able to insert it into
2882
set_internal_auto_increment=
2883
max(set_internal_auto_increment, new_data->auto_increment)
2885
2896
m_last_part= new_part_id;
2886
2897
if (new_part_id == old_part_id)
2888
2899
DBUG_PRINT("info", ("Update in partition %d", new_part_id));
2889
2900
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
2890
2901
error= m_file[new_part_id]->ha_update_row(old_data, new_data);
2903
if updating an auto_increment column, update
2904
table_share->ha_data->next_auto_inc_val if needed.
2905
(not to be used if auto_increment on secondary field in a multi-
2908
if (table->next_number_field && new_data == table->record[0] &&
2909
!table->s->next_number_keypart)
2910
set_auto_increment_if_higher();
2891
2911
reenable_binlog(thd);
4504
4536
int ha_partition::info(uint flag)
4506
handler *file, **file_array;
4507
DBUG_ENTER("ha_partition:info");
4538
DBUG_ENTER("ha_partition::info");
4509
4540
if (flag & HA_STATUS_AUTO)
4511
ulonglong auto_increment_value= 0;
4542
bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0);
4543
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
4512
4544
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
4517
file->info(HA_STATUS_AUTO);
4518
set_if_bigger(auto_increment_value, file->stats.auto_increment_value);
4519
} while (*(++file_array));
4520
stats.auto_increment_value= auto_increment_value;
4545
if (!table->found_next_number_field)
4546
stats.auto_increment_value= 0;
4547
else if (ha_data->auto_inc_initialized)
4549
lock_auto_increment();
4550
stats.auto_increment_value= ha_data->next_auto_inc_val;
4551
unlock_auto_increment();
4555
lock_auto_increment();
4556
/* to avoid two concurrent initializations, check again when locked */
4557
if (ha_data->auto_inc_initialized)
4558
stats.auto_increment_value= ha_data->next_auto_inc_val;
4561
handler *file, **file_array;
4562
ulonglong auto_increment_value= 0;
4565
("checking all partitions for auto_increment_value"));
4569
file->info(HA_STATUS_AUTO);
4570
set_if_bigger(auto_increment_value,
4571
file->stats.auto_increment_value);
4572
} while (*(++file_array));
4574
DBUG_ASSERT(auto_increment_value);
4575
stats.auto_increment_value= auto_increment_value;
4576
if (auto_inc_is_first_in_idx)
4578
set_if_bigger(ha_data->next_auto_inc_val, auto_increment_value);
4579
ha_data->auto_inc_initialized= TRUE;
4580
DBUG_PRINT("info", ("initializing next_auto_inc_val to %lu",
4581
(ulong) ha_data->next_auto_inc_val));
4584
unlock_auto_increment();
4522
4587
if (flag & HA_STATUS_VARIABLE)
4680
4748
stat_info->update_time= file->stats.update_time;
4681
4749
stat_info->check_time= file->stats.check_time;
4682
4750
stat_info->check_sum= 0;
4683
if (file->ha_table_flags() & HA_HAS_CHECKSUM)
4751
if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
4684
4752
stat_info->check_sum= file->checksum();
4690
General function to prepare handler for certain behavior
4758
General function to prepare handler for certain behavior.
4760
@param[in] operation operation to execute
4694
4761
operation Operation type for extra call
4765
@retval >0 error code
4701
4769
extra() is called whenever the server wishes to send a hint to
4702
4770
the storage engine. The MyISAM engine implements the most hints.
4704
4772
We divide the parameters into the following categories:
4705
1) Parameters used by most handlers
4706
2) Parameters used by some non-MyISAM handlers
4707
3) Parameters used only by MyISAM
4708
4) Parameters only used by temporary tables for query processing
4709
5) Parameters only used by MyISAM internally
4710
6) Parameters not used at all
4711
7) Parameters only used by federated tables for query processing
4712
8) Parameters only used by NDB
4773
1) Operations used by most handlers
4774
2) Operations used by some non-MyISAM handlers
4775
3) Operations used only by MyISAM
4776
4) Operations only used by temporary tables for query processing
4777
5) Operations only used by MyISAM internally
4778
6) Operations not used at all
4779
7) Operations only used by federated tables for query processing
4780
8) Operations only used by NDB
4781
9) Operations only used by MERGE
4714
4783
The partition handler need to handle category 1), 2) and 3).
4716
1) Parameters used by most handlers
4785
1) Operations used by most handlers
4717
4786
-----------------------------------
4718
4787
HA_EXTRA_RESET:
4719
4788
This option is used by most handlers and it resets the handler state
4965
5037
HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
4966
5038
Only used by MyISAM, never called.
4968
6) Parameters not used at all
5040
6) Operations not used at all
4969
5041
-----------------------------
4970
5042
HA_EXTRA_KEY_CACHE:
4971
5043
HA_EXTRA_NO_KEY_CACHE:
4972
5044
This parameters are no longer used and could be removed.
4974
7) Parameters only used by federated tables for query processing
5046
7) Operations only used by federated tables for query processing
4975
5047
----------------------------------------------------------------
4976
5048
HA_EXTRA_INSERT_WITH_UPDATE:
4977
5049
Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be
4978
5050
executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY.
4980
8) Parameters only used by NDB
5052
8) Operations only used by NDB
4981
5053
------------------------------
4982
5054
HA_EXTRA_DELETE_CANNOT_BATCH:
4983
5055
HA_EXTRA_UPDATE_CANNOT_BATCH:
5069
5149
/* Category 7), used by federated handlers */
5070
5150
case HA_EXTRA_INSERT_WITH_UPDATE:
5071
5151
DBUG_RETURN(loop_extra(operation));
5072
/* Category 8) Parameters only used by NDB */
5152
/* Category 8) Operations only used by NDB */
5073
5153
case HA_EXTRA_DELETE_CANNOT_BATCH:
5074
5154
case HA_EXTRA_UPDATE_CANNOT_BATCH:
5076
5155
/* Currently only NDB use the *_CANNOT_BATCH */
5159
case HA_EXTRA_ORDERBY_LIMIT:
5160
case HA_EXTRA_NO_ORDERBY_LIMIT:
5161
/* ORDERBY_LIMIT is used by Falcon */
5165
/* Category 9) Operations only used by MERGE */
5166
case HA_EXTRA_ADD_CHILDREN_LIST:
5167
case HA_EXTRA_ATTACH_CHILDREN:
5168
case HA_EXTRA_IS_ATTACHED_CHILDREN:
5169
case HA_EXTRA_DETACH_CHILDREN:
5171
/* Special actions for MERGE tables. Ignore. */
5700
5823
MODULE auto increment
5701
5824
****************************************************************************/
5703
void ha_partition::restore_auto_increment(ulonglong)
5827
int ha_partition::reset_auto_increment(ulonglong value)
5705
DBUG_ENTER("ha_partition::restore_auto_increment");
5829
handler **file= m_file;
5831
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
5832
DBUG_ENTER("ha_partition::reset_auto_increment");
5833
lock_auto_increment();
5834
ha_data->auto_inc_initialized= FALSE;
5835
ha_data->next_auto_inc_val= 0;
5838
if ((res= (*file)->ha_reset_auto_increment(value)) != 0)
5840
} while (*(++file));
5841
unlock_auto_increment();
5712
5847
This method is called by update_auto_increment which in turn is called
5713
by the individual handlers as part of write_row. We will always let
5714
the first handler keep track of the auto increment value for all
5848
by the individual handlers as part of write_row. We use the
5849
table_share->ha_data->next_auto_inc_val, or search all
5850
partitions for the highest auto_increment_value if not initialized or
5851
if auto_increment field is a secondary part of a key, we must search
5852
every partition when holding a mutex to be sure of correctness.
5718
5855
void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
5720
5857
ulonglong *first_value,
5721
5858
ulonglong *nb_reserved_values)
5723
ulonglong first_value_part, last_value_part, nb_reserved_values_part,
5724
last_value= ~ (ulonglong) 0;
5725
handler **pos, **end;
5727
5860
DBUG_ENTER("ha_partition::get_auto_increment");
5730
for (pos=m_file, end= m_file+ m_tot_parts; pos != end ; pos++)
5732
first_value_part= *first_value;
5733
(*pos)->get_auto_increment(offset, increment, nb_desired_values,
5734
&first_value_part, &nb_reserved_values_part);
5735
if (first_value_part == ~(ulonglong)(0)) // error in one partition
5737
*first_value= first_value_part;
5738
sql_print_error("Partition failed to reserve auto_increment value");
5742
Partition has reserved an interval. Intersect it with the intervals
5743
already reserved for the previous partitions.
5745
last_value_part= (nb_reserved_values_part == ULONGLONG_MAX) ?
5746
ULONGLONG_MAX : (first_value_part + nb_reserved_values_part * increment);
5747
set_if_bigger(*first_value, first_value_part);
5748
set_if_smaller(last_value, last_value_part);
5750
if (last_value < *first_value) /* empty intersection, error */
5753
When we have an empty intersection, it means that one or more
5754
partitions may have a significantly different autoinc next value.
5755
We should not fail here - it just means that we should try to
5756
find a new reservation making use of the current *first_value
5757
wbich should now be compatible with all partitions.
5762
last_value= ~ (ulonglong) 0;
5763
release_auto_increment();
5767
We should not get here.
5769
sql_print_error("Failed to calculate auto_increment value for partition");
5771
*first_value= ~(ulonglong)(0);
5773
if (increment) // If not check for values
5774
*nb_reserved_values= (last_value == ULONGLONG_MAX) ?
5775
ULONGLONG_MAX : ((last_value - *first_value) / increment);
5861
DBUG_PRINT("info", ("offset: %lu inc: %lu desired_values: %lu "
5862
"first_value: %lu", (ulong) offset, (ulong) increment,
5863
(ulong) nb_desired_values, (ulong) *first_value));
5864
DBUG_ASSERT(increment && nb_desired_values);
5866
if (table->s->next_number_keypart)
5869
next_number_keypart is != 0 if the auto_increment column is a secondary
5870
column in the index (it is allowed in MyISAM)
5872
DBUG_PRINT("info", ("next_number_keypart != 0"));
5873
ulonglong nb_reserved_values_part;
5874
ulonglong first_value_part, max_first_value;
5875
handler **file= m_file;
5876
first_value_part= max_first_value= *first_value;
5877
/* Must lock and find highest value among all partitions. */
5878
lock_auto_increment();
5881
/* Only nb_desired_values = 1 makes sense */
5882
(*file)->get_auto_increment(offset, increment, 1,
5883
&first_value_part, &nb_reserved_values_part);
5884
if (first_value_part == ~(ulonglong)(0)) // error in one partition
5886
*first_value= first_value_part;
5887
sql_print_error("Partition failed to reserve auto_increment value");
5888
unlock_auto_increment();
5891
DBUG_PRINT("info", ("first_value_part: %lu", (ulong) first_value_part));
5892
set_if_bigger(max_first_value, first_value_part);
5893
} while (*(++file));
5894
*first_value= max_first_value;
5895
*nb_reserved_values= 1;
5896
unlock_auto_increment();
5901
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
5903
This is initialized in the beginning of the first write_row call.
5905
DBUG_ASSERT(ha_data->auto_inc_initialized);
5907
Get a lock for handling the auto_increment in table_share->ha_data
5908
for avoiding two concurrent statements getting the same number.
5911
lock_auto_increment();
5914
In a multi-row insert statement like INSERT SELECT and LOAD DATA
5915
where the number of candidate rows to insert is not known in advance
5916
we must hold a lock/mutex for the whole statement if we have statement
5917
based replication. Because the statement-based binary log contains
5918
only the first generated value used by the statement, and slaves assumes
5919
all other generated values used by this statement were consecutive to
5920
this first one, we must exclusively lock the generator until the statement
5923
if (!auto_increment_safe_stmt_log_lock &&
5924
thd->lex->sql_command != SQLCOM_INSERT &&
5925
mysql_bin_log.is_open() &&
5926
!thd->current_stmt_binlog_row_based &&
5927
(thd->options & OPTION_BIN_LOG))
5929
DBUG_PRINT("info", ("locking auto_increment_safe_stmt_log_lock"));
5930
auto_increment_safe_stmt_log_lock= TRUE;
5933
/* this gets corrected (for offset/increment) in update_auto_increment */
5934
*first_value= ha_data->next_auto_inc_val;
5935
ha_data->next_auto_inc_val+= nb_desired_values * increment;
5937
unlock_auto_increment();
5938
DBUG_PRINT("info", ("*first_value: %lu", (ulong) *first_value));
5939
*nb_reserved_values= nb_desired_values;
5776
5941
DBUG_VOID_RETURN;
5781
5946
DBUG_ENTER("ha_partition::release_auto_increment");
5783
for (uint i= 0; i < m_tot_parts; i++)
5785
m_file[i]->ha_release_auto_increment();
5948
if (table->s->next_number_keypart)
5950
for (uint i= 0; i < m_tot_parts; i++)
5951
m_file[i]->ha_release_auto_increment();
5953
else if (next_insert_id)
5955
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
5956
ulonglong next_auto_inc_val;
5957
lock_auto_increment();
5958
next_auto_inc_val= ha_data->next_auto_inc_val;
5959
if (next_insert_id < next_auto_inc_val &&
5960
auto_inc_interval_for_cur_row.maximum() >= next_auto_inc_val)
5961
ha_data->next_auto_inc_val= next_insert_id;
5962
DBUG_PRINT("info", ("ha_data->next_auto_inc_val: %lu",
5963
(ulong) ha_data->next_auto_inc_val));
5965
/* Unlock the multi row statement lock taken in get_auto_increment */
5966
if (auto_increment_safe_stmt_log_lock)
5968
auto_increment_safe_stmt_log_lock= FALSE;
5969
DBUG_PRINT("info", ("unlocking auto_increment_safe_stmt_log_lock"));
5972
unlock_auto_increment();
5787
5974
DBUG_VOID_RETURN;