mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Bug#12400341 INNODB CAN LEAVE ORPHAN IBD FILES AROUND
If we meet DB_TOO_MANY_CONCURRENT_TRXS during the execution tab_create_graph from row_create_table_for_mysql(), .ibd file for the table should be created already but was not deleted for the error handling. rb:875 approved by Jimmy Yang
This commit is contained in:
commit
ad6a4986eb
10 changed files with 174 additions and 1 deletions
25
mysql-test/suite/innodb/r/innodb_bug12400341.result
Normal file
25
mysql-test/suite/innodb/r/innodb_bug12400341.result
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
call mtr.add_suppression("InnoDB: Warning: cannot find a free slot for an undo log. Do you have too");
|
||||||
|
show variables like "max_connections";
|
||||||
|
Variable_name Value
|
||||||
|
max_connections 64
|
||||||
|
show variables like "innodb_thread_concurrency";
|
||||||
|
Variable_name Value
|
||||||
|
innodb_thread_concurrency 0
|
||||||
|
show variables like "innodb_file_per_table";
|
||||||
|
Variable_name Value
|
||||||
|
innodb_file_per_table ON
|
||||||
|
drop database if exists mysqltest;
|
||||||
|
create database mysqltest;
|
||||||
|
CREATE TABLE mysqltest.transtable (id int unsigned NOT NULL PRIMARY KEY, val int DEFAULT 0) ENGINE=InnoDB;
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
count(*)
|
||||||
|
33
|
||||||
|
CREATE TABLE mysqltest.testtable (id int unsigned not null primary key) ENGINE=InnoDB;
|
||||||
|
ERROR HY000: Can't create table 'mysqltest.testtable' (errno: 177)
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
count(*)
|
||||||
|
33
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
count(*)
|
||||||
|
33
|
||||||
|
drop database mysqltest;
|
1
mysql-test/suite/innodb/t/innodb_bug12400341-master.opt
Normal file
1
mysql-test/suite/innodb/t/innodb_bug12400341-master.opt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--max_connections=64 --innodb_thread_concurrency=0 --innodb_file_per_table --innodb_rollback_segments=2
|
103
mysql-test/suite/innodb/t/innodb_bug12400341.test
Normal file
103
mysql-test/suite/innodb/t/innodb_bug12400341.test
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
# Test for bug #12400341: INNODB CAN LEAVE ORPHAN IBD FILES AROUND
|
||||||
|
|
||||||
|
-- source include/have_innodb.inc
|
||||||
|
|
||||||
|
if (`select count(*)=0 from information_schema.global_variables where variable_name = 'INNODB_TRX_RSEG_N_SLOTS_DEBUG'`)
|
||||||
|
{
|
||||||
|
--skip Test requires InnoDB built with UNIV_DEBUG definition.
|
||||||
|
}
|
||||||
|
|
||||||
|
call mtr.add_suppression("InnoDB: Warning: cannot find a free slot for an undo log. Do you have too");
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
set @old_innodb_trx_rseg_n_slots_debug = @@innodb_trx_rseg_n_slots_debug;
|
||||||
|
set global innodb_trx_rseg_n_slots_debug = 32;
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
show variables like "max_connections";
|
||||||
|
show variables like "innodb_thread_concurrency";
|
||||||
|
show variables like "innodb_file_per_table";
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists mysqltest;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create database mysqltest;
|
||||||
|
CREATE TABLE mysqltest.transtable (id int unsigned NOT NULL PRIMARY KEY, val int DEFAULT 0) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
#
|
||||||
|
# Insert in 1 transaction which needs over 1 page undo record to avoid the insert_undo cached,
|
||||||
|
# because the cached insert_undo can be reused at "CREATE TABLE" statement later.
|
||||||
|
#
|
||||||
|
START TRANSACTION;
|
||||||
|
let $c = 1024;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
eval INSERT INTO mysqltest.transtable (id) VALUES ($c);
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
let $c = 32;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
# if failed at here, it might be shortage of file descriptors limit.
|
||||||
|
connect (con$c,localhost,root,,);
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill the all undo slots
|
||||||
|
#
|
||||||
|
--disable_query_log
|
||||||
|
let $c = 32;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
connection con$c;
|
||||||
|
START TRANSACTION;
|
||||||
|
eval UPDATE mysqltest.transtable SET val = 1 WHERE id = 33 - $c;
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
--error ER_CANT_CREATE_TABLE
|
||||||
|
CREATE TABLE mysqltest.testtable (id int unsigned not null primary key) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
let $c = 32;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
connection con$c;
|
||||||
|
ROLLBACK;
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
select count(*) from information_schema.processlist;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
let $c = 32;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
disconnect con$c;
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
#
|
||||||
|
# If the isolated .ibd file remained, the drop database should fail.
|
||||||
|
#
|
||||||
|
drop database mysqltest;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
set global innodb_trx_rseg_n_slots_debug = @old_innodb_trx_rseg_n_slots_debug;
|
||||||
|
--enable_query_log
|
|
@ -4,6 +4,7 @@ load data infile "MYSQLTEST_VARDIR/tmp/sys_vars.all_vars.txt" into table t1;
|
||||||
insert into t2 select variable_name from information_schema.global_variables;
|
insert into t2 select variable_name from information_schema.global_variables;
|
||||||
insert into t2 select variable_name from information_schema.session_variables;
|
insert into t2 select variable_name from information_schema.session_variables;
|
||||||
delete from t2 where variable_name='innodb_change_buffering_debug';
|
delete from t2 where variable_name='innodb_change_buffering_debug';
|
||||||
|
delete from t2 where variable_name='innodb_trx_rseg_n_slots_debug';
|
||||||
update t2 set variable_name= replace(variable_name, "PERFORMANCE_SCHEMA_", "PFS_");
|
update t2 set variable_name= replace(variable_name, "PERFORMANCE_SCHEMA_", "PFS_");
|
||||||
select variable_name as `There should be *no* long test name listed below:` from t2
|
select variable_name as `There should be *no* long test name listed below:` from t2
|
||||||
where length(variable_name) > 50;
|
where length(variable_name) > 50;
|
||||||
|
|
|
@ -49,6 +49,7 @@ insert into t2 select variable_name from information_schema.session_variables;
|
||||||
|
|
||||||
# This is only present in debug builds.
|
# This is only present in debug builds.
|
||||||
delete from t2 where variable_name='innodb_change_buffering_debug';
|
delete from t2 where variable_name='innodb_change_buffering_debug';
|
||||||
|
delete from t2 where variable_name='innodb_trx_rseg_n_slots_debug';
|
||||||
|
|
||||||
# Performance schema variables are too long for files named
|
# Performance schema variables are too long for files named
|
||||||
# 'mysql-test/suite/sys_vars/t/' ...
|
# 'mysql-test/suite/sys_vars/t/' ...
|
||||||
|
|
|
@ -11437,6 +11437,13 @@ static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
|
||||||
"trigger a readahead.",
|
"trigger a readahead.",
|
||||||
NULL, NULL, 56, 0, 64, 0);
|
NULL, NULL, 56, 0, 64, 0);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
|
||||||
|
PLUGIN_VAR_RQCMDARG,
|
||||||
|
"Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
|
||||||
|
NULL, NULL, 0, 0, 1024, 0);
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||||
MYSQL_SYSVAR(additional_mem_pool_size),
|
MYSQL_SYSVAR(additional_mem_pool_size),
|
||||||
MYSQL_SYSVAR(autoextend_increment),
|
MYSQL_SYSVAR(autoextend_increment),
|
||||||
|
@ -11506,6 +11513,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||||
MYSQL_SYSVAR(purge_threads),
|
MYSQL_SYSVAR(purge_threads),
|
||||||
MYSQL_SYSVAR(purge_batch_size),
|
MYSQL_SYSVAR(purge_batch_size),
|
||||||
MYSQL_SYSVAR(rollback_segments),
|
MYSQL_SYSVAR(rollback_segments),
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
MYSQL_SYSVAR(trx_rseg_n_slots_debug),
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
|
||||||
|
|
||||||
#include "srv0srv.h"
|
#include "srv0srv.h"
|
||||||
#include "mtr0log.h"
|
#include "mtr0log.h"
|
||||||
|
#include "trx0sys.h"
|
||||||
|
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
Gets a rollback segment header.
|
Gets a rollback segment header.
|
||||||
|
@ -131,7 +132,13 @@ trx_rsegf_undo_find_free(
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
|
|
||||||
for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
|
for (i = 0;
|
||||||
|
#ifndef UNIV_DEBUG
|
||||||
|
i < TRX_RSEG_N_SLOTS;
|
||||||
|
#else
|
||||||
|
i < (trx_rseg_n_slots_debug ? trx_rseg_n_slots_debug : TRX_RSEG_N_SLOTS);
|
||||||
|
#endif
|
||||||
|
i++) {
|
||||||
|
|
||||||
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
|
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,12 @@ trx_id_t
|
||||||
trx_sys_get_new_trx_id(void);
|
trx_sys_get_new_trx_id(void);
|
||||||
/*========================*/
|
/*========================*/
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
|
||||||
|
extern uint trx_rseg_n_slots_debug;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Writes a trx id to an index page. In case that the id size changes in
|
Writes a trx id to an index page. In case that the id size changes in
|
||||||
some future version, this function should be used instead of
|
some future version, this function should be used instead of
|
||||||
|
|
|
@ -1991,6 +1991,20 @@ err_exit:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DB_TOO_MANY_CONCURRENT_TRXS:
|
||||||
|
/* We already have .ibd file here. it should be deleted. */
|
||||||
|
|
||||||
|
if (table->space && !fil_delete_tablespace(table->space)) {
|
||||||
|
ut_print_timestamp(stderr);
|
||||||
|
fprintf(stderr,
|
||||||
|
" InnoDB: Error: not able to"
|
||||||
|
" delete tablespace %lu of table ",
|
||||||
|
(ulong) table->space);
|
||||||
|
ut_print_name(stderr, trx, TRUE, table->name);
|
||||||
|
fputs("!\n", stderr);
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
case DB_DUPLICATE_KEY:
|
case DB_DUPLICATE_KEY:
|
||||||
default:
|
default:
|
||||||
/* We may also get err == DB_ERROR if the .ibd file for the
|
/* We may also get err == DB_ERROR if the .ibd file for the
|
||||||
|
|
|
@ -134,6 +134,11 @@ UNIV_INTERN mysql_pfs_key_t trx_doublewrite_mutex_key;
|
||||||
UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key;
|
UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key;
|
||||||
#endif /* UNIV_PFS_MUTEX */
|
#endif /* UNIV_PFS_MUTEX */
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
|
||||||
|
uint trx_rseg_n_slots_debug = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
/** This is used to track the maximum file format id known to InnoDB. It's
|
/** This is used to track the maximum file format id known to InnoDB. It's
|
||||||
updated via SET GLOBAL innodb_file_format_max = 'x' or when we open
|
updated via SET GLOBAL innodb_file_format_max = 'x' or when we open
|
||||||
|
|
Loading…
Reference in a new issue