Merge with main Maria tree
This commit is contained in:
commit
7f91cf0861
@ -2365,6 +2365,10 @@ int ha_maria::external_lock(THD *thd, int lock_type)
|
|||||||
We always re-enable, don't rely on thd->transaction.on as it is
|
We always re-enable, don't rely on thd->transaction.on as it is
|
||||||
sometimes reset to true after unlocking (see mysql_truncate() for a
|
sometimes reset to true after unlocking (see mysql_truncate() for a
|
||||||
partitioned table based on Maria).
|
partitioned table based on Maria).
|
||||||
|
Note that we can come here without having an exclusive lock on the
|
||||||
|
table, for example in this case:
|
||||||
|
external_lock(F_(WR|RD)LCK); thr_lock() which fails due to lock
|
||||||
|
abortion; external_lock(F_UNLCK).
|
||||||
*/
|
*/
|
||||||
if (_ma_reenable_logging_for_table(file, TRUE))
|
if (_ma_reenable_logging_for_table(file, TRUE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
@ -260,6 +260,7 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
|
|||||||
my_bool _ma_bitmap_end(MARIA_SHARE *share)
|
my_bool _ma_bitmap_end(MARIA_SHARE *share)
|
||||||
{
|
{
|
||||||
my_bool res= _ma_bitmap_flush(share);
|
my_bool res= _ma_bitmap_flush(share);
|
||||||
|
safe_mutex_assert_owner(&share->close_lock);
|
||||||
pthread_mutex_destroy(&share->bitmap.bitmap_lock);
|
pthread_mutex_destroy(&share->bitmap.bitmap_lock);
|
||||||
pthread_cond_destroy(&share->bitmap.bitmap_cond);
|
pthread_cond_destroy(&share->bitmap.bitmap_cond);
|
||||||
delete_dynamic(&share->bitmap.pinned_pages);
|
delete_dynamic(&share->bitmap.pinned_pages);
|
||||||
|
@ -453,7 +453,7 @@ my_bool _ma_once_end_block_record(MARIA_SHARE *share)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We de-assign the id even though index has not been flushed, this is ok
|
We de-assign the id even though index has not been flushed, this is ok
|
||||||
as intern_lock serializes us with a Checkpoint looking at our share.
|
as close_lock serializes us with a Checkpoint looking at our share.
|
||||||
*/
|
*/
|
||||||
translog_deassign_id_from_share(share);
|
translog_deassign_id_from_share(share);
|
||||||
}
|
}
|
||||||
|
@ -784,10 +784,8 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
!(share->in_checkpoint & MARIA_CHECKPOINT_SEEN_IN_LOOP))
|
!(share->in_checkpoint & MARIA_CHECKPOINT_SEEN_IN_LOOP))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Why we didn't take intern_lock above: table had in_checkpoint==0 so no
|
Apart from us, only maria_close() reads/sets in_checkpoint but cannot
|
||||||
thread could set in_checkpoint. And no thread needs to know that we
|
run now as we hold THR_LOCK_maria.
|
||||||
are setting in_checkpoint, because only maria_close() needs it and
|
|
||||||
cannot run now as we hold THR_LOCK_maria.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
This table is relevant for checkpoint and not already seen. Mark it,
|
This table is relevant for checkpoint and not already seen. Mark it,
|
||||||
@ -887,7 +885,10 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
my_bool ignore_share;
|
my_bool ignore_share;
|
||||||
if (!(share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME))
|
if (!(share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME))
|
||||||
{
|
{
|
||||||
/* No need for a mutex to read the above, only us can write this flag */
|
/*
|
||||||
|
No need for a mutex to read the above, only us can write *this* bit of
|
||||||
|
the in_checkpoint bitmap
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -956,6 +957,14 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
|
|
||||||
/* OS file descriptors are ints which we stored in 4 bytes */
|
/* OS file descriptors are ints which we stored in 4 bytes */
|
||||||
compile_time_assert(sizeof(int) <= 4);
|
compile_time_assert(sizeof(int) <= 4);
|
||||||
|
/*
|
||||||
|
Protect against maria_close() (which does some memory freeing in
|
||||||
|
MARIA_FILE_BITMAP) with close_lock. intern_lock is not
|
||||||
|
sufficient as we, as well as maria_close(), are going to unlock
|
||||||
|
intern_lock in the middle of manipulating the table. Serializing us and
|
||||||
|
maria_close() should help avoid problems.
|
||||||
|
*/
|
||||||
|
pthread_mutex_lock(&share->close_lock);
|
||||||
pthread_mutex_lock(&share->intern_lock);
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
/*
|
/*
|
||||||
Tables in a normal state have their two file descriptors open.
|
Tables in a normal state have their two file descriptors open.
|
||||||
@ -1045,6 +1054,20 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
each checkpoint if the table was once written and then not anymore.
|
each checkpoint if the table was once written and then not anymore.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
_ma_bitmap_flush_all() may wait, so don't keep intern_lock as
|
||||||
|
otherwise this would deadlock with allocate_and_write_block_record()
|
||||||
|
calling _ma_set_share_data_file_length()
|
||||||
|
*/
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
|
||||||
|
if (!ignore_share)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
share->bitmap is valid because it's destroyed under close_lock which
|
||||||
|
we hold.
|
||||||
|
*/
|
||||||
if (_ma_bitmap_flush_all(share))
|
if (_ma_bitmap_flush_all(share))
|
||||||
{
|
{
|
||||||
sync_error= 1;
|
sync_error= 1;
|
||||||
@ -1057,23 +1080,28 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
Clean up any unused states.
|
Clean up any unused states.
|
||||||
TODO: Only do this call if there has been # (10?) ended transactions
|
TODO: Only do this call if there has been # (10?) ended transactions
|
||||||
since last call.
|
since last call.
|
||||||
|
We had to release intern_lock to respect lock order with LOCK_trn_list.
|
||||||
*/
|
*/
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
_ma_remove_not_visible_states_with_lock(share, FALSE);
|
||||||
_ma_remove_not_visible_states_with_lock(share);
|
|
||||||
pthread_mutex_lock(&share->intern_lock);
|
|
||||||
|
|
||||||
if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)
|
if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)
|
||||||
{
|
{
|
||||||
/* maria_close() left us to free the share */
|
/*
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
maria_close() left us free the share. When it run it set share->id
|
||||||
|
to 0. As it run before we locked close_lock, we should have seen this
|
||||||
|
and so this assertion should be true:
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(ignore_share);
|
||||||
pthread_mutex_destroy(&share->intern_lock);
|
pthread_mutex_destroy(&share->intern_lock);
|
||||||
|
pthread_mutex_unlock(&share->close_lock);
|
||||||
|
pthread_mutex_destroy(&share->close_lock);
|
||||||
my_free((uchar *)share, MYF(0));
|
my_free((uchar *)share, MYF(0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* share goes back to normal state */
|
/* share goes back to normal state */
|
||||||
share->in_checkpoint= 0;
|
share->in_checkpoint= 0;
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->close_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,6 +47,7 @@ int maria_close(register MARIA_HA *info)
|
|||||||
if (maria_lock_database(info,F_UNLCK))
|
if (maria_lock_database(info,F_UNLCK))
|
||||||
error=my_errno;
|
error=my_errno;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_lock(&share->close_lock);
|
||||||
pthread_mutex_lock(&share->intern_lock);
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
|
|
||||||
if (share->options & HA_OPTION_READ_ONLY_DATA)
|
if (share->options & HA_OPTION_READ_ONLY_DATA)
|
||||||
@ -125,22 +126,30 @@ int maria_close(register MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
|
DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
|
||||||
if (share->in_checkpoint == MARIA_CHECKPOINT_LOOKS_AT_ME)
|
/*
|
||||||
|
We assign -1 because checkpoint does not need to flush (in case we
|
||||||
|
have concurrent checkpoint if no then we do not need it here also)
|
||||||
|
*/
|
||||||
|
share->kfile.file= -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remember share->history for future opens
|
||||||
|
|
||||||
|
We have to unlock share->intern_lock then lock it after
|
||||||
|
LOCK_trn_list (trnman_lock()) to avoid dead locks.
|
||||||
|
*/
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
_ma_remove_not_visible_states_with_lock(share, TRUE);
|
||||||
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
|
|
||||||
|
if (share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME)
|
||||||
{
|
{
|
||||||
share->kfile.file= -1; /* because Checkpoint does not need to flush */
|
|
||||||
/* we cannot my_free() the share, Checkpoint would see a bad pointer */
|
/* we cannot my_free() the share, Checkpoint would see a bad pointer */
|
||||||
share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME;
|
share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
share_can_be_freed= TRUE;
|
share_can_be_freed= TRUE;
|
||||||
|
|
||||||
/*
|
|
||||||
Remember share->history for future opens
|
|
||||||
Here we take share->intern_lock followed by trans_lock but this is
|
|
||||||
safe as no other thread one can use 'share' here.
|
|
||||||
*/
|
|
||||||
share->state_history= _ma_remove_not_visible_states(share->state_history,
|
|
||||||
1, 0);
|
|
||||||
if (share->state_history)
|
if (share->state_history)
|
||||||
{
|
{
|
||||||
MARIA_STATE_HISTORY_CLOSED *history;
|
MARIA_STATE_HISTORY_CLOSED *history;
|
||||||
@ -161,10 +170,17 @@ int maria_close(register MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
pthread_mutex_unlock(&THR_LOCK_maria);
|
pthread_mutex_unlock(&THR_LOCK_maria);
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
pthread_mutex_unlock(&share->close_lock);
|
||||||
if (share_can_be_freed)
|
if (share_can_be_freed)
|
||||||
{
|
{
|
||||||
(void) pthread_mutex_destroy(&share->intern_lock);
|
(void) pthread_mutex_destroy(&share->intern_lock);
|
||||||
|
(void) pthread_mutex_destroy(&share->close_lock);
|
||||||
my_free((uchar *)share, MYF(0));
|
my_free((uchar *)share, MYF(0));
|
||||||
|
/*
|
||||||
|
If share cannot be freed, it's because checkpoint has previously
|
||||||
|
recorded to include this share in the checkpoint and so is soon going to
|
||||||
|
look at some of its content (share->in_checkpoint/id/last_version).
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
my_free(info->ftparser_param, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(info->ftparser_param, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
if (info->dfile.file >= 0)
|
if (info->dfile.file >= 0)
|
||||||
|
@ -819,6 +819,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST);
|
||||||
pthread_mutex_init(&share->key_del_lock, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&share->key_del_lock, MY_MUTEX_INIT_FAST);
|
||||||
pthread_cond_init(&share->key_del_cond, 0);
|
pthread_cond_init(&share->key_del_cond, 0);
|
||||||
|
pthread_mutex_init(&share->close_lock, MY_MUTEX_INIT_FAST);
|
||||||
for (i=0; i<keys; i++)
|
for (i=0; i<keys; i++)
|
||||||
VOID(my_rwlock_init(&share->keyinfo[i].root_lock, NULL));
|
VOID(my_rwlock_init(&share->keyinfo[i].root_lock, NULL));
|
||||||
VOID(my_rwlock_init(&share->mmap_lock, NULL));
|
VOID(my_rwlock_init(&share->mmap_lock, NULL));
|
||||||
|
@ -3276,6 +3276,8 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info,
|
|||||||
/**
|
/**
|
||||||
Re-enables logging for a table which had it temporarily disabled.
|
Re-enables logging for a table which had it temporarily disabled.
|
||||||
|
|
||||||
|
Only the thread which disabled logging is allowed to reenable it.
|
||||||
|
|
||||||
@param info table
|
@param info table
|
||||||
@param flush_pages if function needs to flush pages first
|
@param flush_pages if function needs to flush pages first
|
||||||
*/
|
*/
|
||||||
|
@ -168,7 +168,6 @@ MARIA_STATE_HISTORY
|
|||||||
|
|
||||||
if (all && parent == &org_history->next)
|
if (all && parent == &org_history->next)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(trnman_is_locked == 0);
|
|
||||||
/* There is only one state left. Delete this if it's visible for all */
|
/* There is only one state left. Delete this if it's visible for all */
|
||||||
if (last_trid < trnman_get_min_trid())
|
if (last_trid < trnman_get_min_trid())
|
||||||
{
|
{
|
||||||
@ -183,6 +182,11 @@ MARIA_STATE_HISTORY
|
|||||||
/**
|
/**
|
||||||
@brief Remove not used state history
|
@brief Remove not used state history
|
||||||
|
|
||||||
|
@param share Maria table information
|
||||||
|
@param all 1 if we should delete the first state if it's
|
||||||
|
visible for all. For the moment this is only used
|
||||||
|
on close() of table.
|
||||||
|
|
||||||
@notes
|
@notes
|
||||||
share and trnman are not locked.
|
share and trnman are not locked.
|
||||||
|
|
||||||
@ -191,14 +195,19 @@ MARIA_STATE_HISTORY
|
|||||||
takes share->intern_lock.
|
takes share->intern_lock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share)
|
void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share,
|
||||||
|
my_bool all)
|
||||||
{
|
{
|
||||||
trnman_lock();
|
my_bool is_lock_trman;
|
||||||
|
if ((is_lock_trman= trman_is_inited()))
|
||||||
|
trnman_lock();
|
||||||
|
|
||||||
pthread_mutex_lock(&share->intern_lock);
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
share->state_history= _ma_remove_not_visible_states(share->state_history, 0,
|
share->state_history= _ma_remove_not_visible_states(share->state_history,
|
||||||
1);
|
all, 1);
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
trnman_unlock();
|
if (is_lock_trman)
|
||||||
|
trnman_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
|
|||||||
my_bool _ma_row_visible_always(MARIA_HA *info);
|
my_bool _ma_row_visible_always(MARIA_HA *info);
|
||||||
my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
|
my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
|
||||||
my_bool _ma_row_visible_transactional_table(MARIA_HA *info);
|
my_bool _ma_row_visible_transactional_table(MARIA_HA *info);
|
||||||
void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share);
|
void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share,
|
||||||
|
my_bool all);
|
||||||
void _ma_remove_table_from_trnman(struct st_maria_share *share, TRN *trn);
|
void _ma_remove_table_from_trnman(struct st_maria_share *share, TRN *trn);
|
||||||
void _ma_reset_history(struct st_maria_share *share);
|
void _ma_reset_history(struct st_maria_share *share);
|
||||||
|
@ -353,7 +353,7 @@ typedef struct st_maria_share
|
|||||||
PAGECACHE_FILE kfile; /* Shared keyfile */
|
PAGECACHE_FILE kfile; /* Shared keyfile */
|
||||||
File data_file; /* Shared data file */
|
File data_file; /* Shared data file */
|
||||||
int mode; /* mode of file on open */
|
int mode; /* mode of file on open */
|
||||||
uint reopen; /* How many times reopened */
|
uint reopen; /* How many times opened */
|
||||||
uint in_trans; /* Number of references by trn */
|
uint in_trans; /* Number of references by trn */
|
||||||
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
|
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
|
||||||
uint block_size; /* block_size of keyfile & data file*/
|
uint block_size; /* block_size of keyfile & data file*/
|
||||||
@ -362,7 +362,10 @@ typedef struct st_maria_share
|
|||||||
myf write_flag;
|
myf write_flag;
|
||||||
enum data_file_type data_file_type;
|
enum data_file_type data_file_type;
|
||||||
enum pagecache_page_type page_type; /* value depending transactional */
|
enum pagecache_page_type page_type; /* value depending transactional */
|
||||||
uint8 in_checkpoint; /**< if Checkpoint looking at table */
|
/**
|
||||||
|
if Checkpoint looking at table; protected by close_lock or THR_LOCK_maria
|
||||||
|
*/
|
||||||
|
uint8 in_checkpoint;
|
||||||
my_bool temporary;
|
my_bool temporary;
|
||||||
/* Below flag is needed to make log tables work with concurrent insert */
|
/* Below flag is needed to make log tables work with concurrent insert */
|
||||||
my_bool is_log_table;
|
my_bool is_log_table;
|
||||||
@ -386,9 +389,20 @@ typedef struct st_maria_share
|
|||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
THR_LOCK lock;
|
THR_LOCK lock;
|
||||||
void (*lock_restore_status)(void *);
|
void (*lock_restore_status)(void *);
|
||||||
pthread_mutex_t intern_lock; /* Locking for use with _locking */
|
/**
|
||||||
|
Protects kfile, dfile, most members of the state, state disk writes,
|
||||||
|
versioning information (like in_trans, state_history).
|
||||||
|
@todo find the exhaustive list.
|
||||||
|
*/
|
||||||
|
pthread_mutex_t intern_lock;
|
||||||
pthread_mutex_t key_del_lock;
|
pthread_mutex_t key_del_lock;
|
||||||
pthread_cond_t key_del_cond;
|
pthread_cond_t key_del_cond;
|
||||||
|
/**
|
||||||
|
_Always_ held while closing table; prevents checkpoint from looking at
|
||||||
|
structures freed during closure (like bitmap). If you need close_lock and
|
||||||
|
intern_lock, lock them in this order.
|
||||||
|
*/
|
||||||
|
pthread_mutex_t close_lock;
|
||||||
#endif
|
#endif
|
||||||
my_off_t mmaped_length;
|
my_off_t mmaped_length;
|
||||||
uint nonmmaped_inserts; /* counter of writing in
|
uint nonmmaped_inserts; /* counter of writing in
|
||||||
|
@ -881,6 +881,7 @@ my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
|
|||||||
|
|
||||||
if (!trnman_is_locked)
|
if (!trnman_is_locked)
|
||||||
pthread_mutex_lock(&LOCK_trn_list);
|
pthread_mutex_lock(&LOCK_trn_list);
|
||||||
|
safe_mutex_assert_owner(&LOCK_trn_list);
|
||||||
for (trn= active_list_min.next; trn != &active_list_max; trn= trn->next)
|
for (trn= active_list_min.next; trn != &active_list_max; trn= trn->next)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -909,6 +910,7 @@ void trnman_lock()
|
|||||||
pthread_mutex_lock(&LOCK_trn_list);
|
pthread_mutex_lock(&LOCK_trn_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
unlock transaction list
|
unlock transaction list
|
||||||
*/
|
*/
|
||||||
@ -917,3 +919,13 @@ void trnman_unlock()
|
|||||||
{
|
{
|
||||||
pthread_mutex_unlock(&LOCK_trn_list);
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Is trman initialized
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool trman_is_inited()
|
||||||
|
{
|
||||||
|
return (short_trid_to_active_trn != NULL);
|
||||||
|
}
|
||||||
|
@ -69,5 +69,6 @@ my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
|
|||||||
#define transid_korr(P) uint6korr(P)
|
#define transid_korr(P) uint6korr(P)
|
||||||
void trnman_lock();
|
void trnman_lock();
|
||||||
void trnman_unlock();
|
void trnman_unlock();
|
||||||
|
my_bool trman_is_inited();
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user