Skip to content

Commit dbcbee1

Browse files
committed
Merge 10.6 into 10.7
2 parents 9e27e53 + cf437f6 commit dbcbee1

File tree

6 files changed

+126
-53
lines changed

6 files changed

+126
-53
lines changed

sql/handler.cc

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,12 +1001,30 @@ void ha_end_backup()
10011001
PLUGIN_IS_DELETED|PLUGIN_IS_READY, 0);
10021002
}
10031003

1004-
void handler::log_not_redoable_operation(const char *operation)
1004+
/*
1005+
Take a lock to block MDL_BACKUP_DDL (used by maria-backup) until
1006+
the DDL operation is taking place
1007+
*/
1008+
1009+
bool handler::log_not_redoable_operation(const char *operation)
10051010
{
10061011
DBUG_ENTER("log_not_redoable_operation");
10071012
if (table->s->tmp_table == NO_TMP_TABLE)
10081013
{
1014+
/*
1015+
Take a lock to ensure that mariadb-backup will notice the
1016+
new log entry (and re-copy the table if needed).
1017+
*/
1018+
THD *thd= table->in_use;
1019+
MDL_request mdl_backup;
10091020
backup_log_info ddl_log;
1021+
1022+
MDL_REQUEST_INIT(&mdl_backup, MDL_key::BACKUP, "", "", MDL_BACKUP_DDL,
1023+
MDL_STATEMENT);
1024+
if (thd->mdl_context.acquire_lock(&mdl_backup,
1025+
thd->variables.lock_wait_timeout))
1026+
DBUG_RETURN(1);
1027+
10101028
bzero(&ddl_log, sizeof(ddl_log));
10111029
lex_string_set(&ddl_log.query, operation);
10121030
/*
@@ -1022,7 +1040,7 @@ void handler::log_not_redoable_operation(const char *operation)
10221040
ddl_log.org_table_id= table->s->tabledef_version;
10231041
backup_log_ddl(&ddl_log);
10241042
}
1025-
DBUG_VOID_RETURN;
1043+
DBUG_RETURN(0);
10261044
}
10271045

10281046
/*

sql/handler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5123,7 +5123,7 @@ class handler :public Sql_alloc
51235123
return (lower_case_table_names == 2 && !(ha_table_flags() & HA_FILE_BASED));
51245124
}
51255125

5126-
void log_not_redoable_operation(const char *operation);
5126+
bool log_not_redoable_operation(const char *operation);
51275127
protected:
51285128
Handler_share *get_ha_share_ptr();
51295129
void set_ha_share_ptr(Handler_share *arg_ha_share);

storage/innobase/trx/trx0purge.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,11 +766,12 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
766766
auto block= reinterpret_cast<buf_block_t*>(bpage);
767767
if (!bpage->lock.x_lock_try())
768768
{
769+
rescan:
769770
/* Let buf_pool_t::release_freed_page() proceed. */
770771
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
771-
std::this_thread::yield();
772+
mysql_mutex_lock(&buf_pool.mutex);
772773
mysql_mutex_lock(&buf_pool.flush_list_mutex);
773-
rescan:
774+
mysql_mutex_unlock(&buf_pool.mutex);
774775
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
775776
continue;
776777
}

storage/maria/ha_maria.cc

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ extern "C" {
872872

873873
int _ma_killed_ptr(HA_CHECK *param)
874874
{
875-
if (likely(thd_killed((THD*)param->thd)) == 0)
875+
if (!param->thd || likely(thd_killed((THD*)param->thd)) == 0)
876876
return 0;
877877
my_errno= HA_ERR_ABORTED_BY_USER;
878878
return 1;
@@ -901,9 +901,10 @@ int _ma_killed_ptr(HA_CHECK *param)
901901
void _ma_report_progress(HA_CHECK *param, ulonglong progress,
902902
ulonglong max_progress)
903903
{
904-
thd_progress_report((THD*)param->thd,
905-
progress + max_progress * param->stage,
906-
max_progress * param->max_stage);
904+
if (param->thd)
905+
thd_progress_report((THD*)param->thd,
906+
progress + max_progress * param->stage,
907+
max_progress * param->max_stage);
907908
}
908909

909910

@@ -2263,16 +2264,19 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags)
22632264
{
22642265
bulk_insert_single_undo= BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR;
22652266
write_log_record_for_bulk_insert(file);
2266-
_ma_tmp_disable_logging_for_table(file, TRUE);
22672267
/*
22682268
Pages currently in the page cache have type PAGECACHE_LSN_PAGE, we
22692269
are not allowed to overwrite them with PAGECACHE_PLAIN_PAGE, so
22702270
throw them away. It is not losing data, because we just wrote and
22712271
forced an UNDO which will for sure empty the table if we crash. The
22722272
upcoming unique-key insertions however need a proper index, so we
22732273
cannot leave the corrupted on-disk index file, thus we truncate it.
2274+
2275+
The following call will log the truncate and update the lsn for the table
2276+
to ensure that all redo's before this will be ignored.
22742277
*/
22752278
maria_delete_all_rows(file);
2279+
_ma_tmp_disable_logging_for_table(file, TRUE);
22762280
}
22772281
}
22782282
else if (!file->bulk_insert &&
@@ -2303,23 +2307,58 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags)
23032307

23042308
int ha_maria::end_bulk_insert()
23052309
{
2306-
int first_error, error;
2307-
my_bool abort= file->s->deleting;
2310+
int first_error, first_errno= 0, error;
2311+
my_bool abort= file->s->deleting, empty_table= 0;
2312+
uint enable_index_mode= HA_KEY_SWITCH_NONUNIQ_SAVE;
23082313
DBUG_ENTER("ha_maria::end_bulk_insert");
23092314

23102315
if ((first_error= maria_end_bulk_insert(file, abort)))
2316+
{
2317+
first_errno= my_errno;
23112318
abort= 1;
2319+
}
23122320

23132321
if ((error= maria_extra(file, HA_EXTRA_NO_CACHE, 0)))
23142322
{
2315-
first_error= first_error ? first_error : error;
2323+
if (!first_error)
2324+
{
2325+
first_error= error;
2326+
first_errno= my_errno;
2327+
}
23162328
abort= 1;
23172329
}
23182330

2319-
if (!abort && can_enable_indexes)
2320-
if ((error= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)))
2321-
first_error= first_error ? first_error : error;
2331+
if (bulk_insert_single_undo != BULK_INSERT_NONE)
2332+
{
2333+
if (log_not_redoable_operation("BULK_INSERT"))
2334+
{
2335+
/* Got lock timeout. revert back to empty file and give error */
2336+
if (!first_error)
2337+
{
2338+
first_error= 1;
2339+
first_errno= my_errno;
2340+
}
2341+
enable_index_mode= HA_KEY_SWITCH_ALL;
2342+
empty_table= 1;
2343+
/*
2344+
Ignore all changed pages, required by _ma_renable_logging_for_table()
2345+
*/
2346+
_ma_flush_table_files(file, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
2347+
FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED);
2348+
}
2349+
}
23222350

2351+
if (!abort && can_enable_indexes)
2352+
{
2353+
if ((error= enable_indexes(enable_index_mode)))
2354+
{
2355+
if (!first_error)
2356+
{
2357+
first_error= 1;
2358+
first_errno= my_errno;
2359+
}
2360+
}
2361+
}
23232362
if (bulk_insert_single_undo != BULK_INSERT_NONE)
23242363
{
23252364
/*
@@ -2328,12 +2367,23 @@ int ha_maria::end_bulk_insert()
23282367
*/
23292368
if ((error= _ma_reenable_logging_for_table(file,
23302369
bulk_insert_single_undo ==
2331-
BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR)))
2332-
first_error= first_error ? first_error : error;
2333-
bulk_insert_single_undo= BULK_INSERT_NONE; // Safety
2334-
log_not_redoable_operation("BULK_INSERT");
2370+
BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR)) &&
2371+
!empty_table)
2372+
{
2373+
if (!first_error)
2374+
{
2375+
first_error= 1;
2376+
first_errno= my_errno;
2377+
}
2378+
}
2379+
bulk_insert_single_undo= BULK_INSERT_NONE; // Safety if called again
23352380
}
2381+
if (empty_table)
2382+
maria_delete_all_rows(file);
2383+
23362384
can_enable_indexes= 0;
2385+
if (first_error)
2386+
my_errno= first_errno;
23372387
DBUG_RETURN(first_error);
23382388
}
23392389

storage/maria/ma_delete_all.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ int maria_delete_all_rows(MARIA_HA *info)
6464
*/
6565
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
6666
uchar log_data[FILEID_STORE_SIZE];
67+
my_bool error;
6768
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
6869
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
6970
if (unlikely(translog_write_record(&lsn, LOGREC_REDO_DELETE_ALL,
@@ -78,6 +79,32 @@ int maria_delete_all_rows(MARIA_HA *info)
7879
*/
7980
if (_ma_mark_file_changed(share))
8081
goto err;
82+
83+
/*
84+
Because LOGREC_REDO_DELETE_ALL does not operate on pages, it has the
85+
following problem:
86+
delete_all; inserts (redo_insert); all pages get flushed; checkpoint:
87+
the dirty pages list will be empty. In recovery, delete_all is executed,
88+
but redo_insert are skipped (dirty pages list is empty).
89+
To avoid this, we need to set skip_redo_lsn now, and thus need to sync
90+
files.
91+
Also fixes the problem of:
92+
bulk insert; insert; delete_all; crash:
93+
"bulk insert" is skipped (no REDOs), so if "insert" would not be skipped
94+
(if we didn't update skip_redo_lsn below) then "insert" would be tried
95+
and fail, saying that it sees that the first page has to be created
96+
though the inserted row has rownr>0.
97+
98+
We use lsn-1 below to ensure that the above redo will be executed
99+
*/
100+
error= _ma_state_info_write(share,
101+
MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
102+
MA_STATE_INFO_WRITE_LOCK) ||
103+
_ma_update_state_lsns(share, lsn-1, info->trn->trid, FALSE, FALSE) ||
104+
_ma_sync_table_files(info);
105+
info->trn->rec_lsn= LSN_IMPOSSIBLE;
106+
if (error)
107+
goto err;
81108
}
82109
else
83110
{
@@ -113,28 +140,9 @@ int maria_delete_all_rows(MARIA_HA *info)
113140

114141
if (log_record)
115142
{
116-
/*
117-
Because LOGREC_REDO_DELETE_ALL does not operate on pages, it has the
118-
following problem:
119-
delete_all; inserts (redo_insert); all pages get flushed; checkpoint:
120-
the dirty pages list will be empty. In recovery, delete_all is executed,
121-
but redo_insert are skipped (dirty pages list is empty).
122-
To avoid this, we need to set skip_redo_lsn now, and thus need to sync
123-
files.
124-
Also fixes the problem of:
125-
bulk insert; insert; delete_all; crash:
126-
"bulk insert" is skipped (no REDOs), so if "insert" would not be skipped
127-
(if we didn't update skip_redo_lsn below) then "insert" would be tried
128-
and fail, saying that it sees that the first page has to be created
129-
though the inserted row has rownr>0.
130-
*/
131-
my_bool error= _ma_state_info_write(share,
132-
MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
133-
MA_STATE_INFO_WRITE_LOCK) ||
134-
_ma_update_state_lsns(share, lsn, info->trn->trid, FALSE, FALSE) ||
135-
_ma_sync_table_files(info);
136-
info->trn->rec_lsn= LSN_IMPOSSIBLE;
137-
if (error)
143+
/* Update lsn to signal that the above redo does not have to be executed anymore */
144+
if ( _ma_update_state_lsns(share, lsn, info->trn->trid, FALSE, FALSE) ||
145+
_ma_sync_table_files(info))
138146
goto err;
139147
}
140148

storage/maria/ma_recovery.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,16 +1175,6 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE)
11751175
/* We try to get table first, so that we get the table in in the trace log */
11761176
info= get_MARIA_HA_from_REDO_record(rec);
11771177

1178-
if (skip_DDLs)
1179-
{
1180-
/*
1181-
REPAIR is not exactly a DDL, but it manipulates files without logging
1182-
insertions into them.
1183-
*/
1184-
tprint(tracef, "we skip DDLs\n");
1185-
DBUG_RETURN(0);
1186-
}
1187-
11881178
if (!info)
11891179
{
11901180
/* no such table, don't need to warn */
@@ -1196,6 +1186,13 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE)
11961186
tprint(tracef, "we skip repairing crashed table\n");
11971187
DBUG_RETURN(0);
11981188
}
1189+
1190+
if (rec->lsn <= info->s->state.is_of_horizon)
1191+
{
1192+
DBUG_PRINT("info", ("Table is up to date, skipping redo"));
1193+
DBUG_RETURN(0);
1194+
}
1195+
11991196
/*
12001197
Otherwise, the mapping is newer than the table, and our record is newer
12011198
than the mapping, so we can repair.
@@ -1560,7 +1557,6 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD)
15601557
uchar *buff= NULL;
15611558
MARIA_HA *info= get_MARIA_HA_from_REDO_record(rec);
15621559
if (info == NULL || maria_is_crashed(info))
1563-
15641560
{
15651561
/*
15661562
Table was skipped at open time (because later dropped/renamed, not

0 commit comments

Comments
 (0)