mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
The used code is largely based on code from Tencent The problem is that in some rare cases there may be a conflict between .frm files and the files in the storage engine. In this case the DROP TABLE was not able to properly drop the table. Some MariaDB/MySQL forks has solved this by adding a FORCE option to DROP TABLE. After some discussion among MariaDB developers, we concluded that users expects that DROP TABLE should always work, even if the table would not be consistent. There should not be a need to use a separate keyword to ensure that the table is really deleted. The used solution is: - If a .frm table doesn't exists, try dropping the table from all storage engines. - If the .frm table exists but the table does not exist in the engine try dropping the table from all storage engines. - Update storage engines using many table files (.CVS, MyISAM, Aria) to succeed with the drop even if some of the files are missing. - Add HTON_AUTOMATIC_DELETE_TABLE to handlerton's where delete_table() is not needed and always succeed. This is used by ha_delete_table_force() to know which handlers to ignore when trying to drop a table without a .frm file. The disadvantage of this solution is that a DROP TABLE on a non existing table will be a bit slower as we have to ask all active storage engines if they know anything about the table. Other things: - Added a new flag MY_IGNORE_ENOENT to my_delete() to not give an error if the file doesn't exist. This simplifies some of the code. - Don't clear thd->error in ha_delete_table() if there was an active error. This is a bug fix. - handler::delete_table() will not abort if first file doesn't exists. This is bug fix to handle the case when a drop table was aborted in the middle. - Cleaned up mysql_rm_table_no_locks() to ensure that if_exists uses same code path as when it's not used. - Use non_existing_Table_error() to detect if table didn't exists. Old code used different errors tests in different position. - Table_triggers_list::drop_all_triggers() now drops trigger file if it can't be parsed instead of leaving it hanging around (bug fix) - InnoDB doesn't anymore print error about .frm file out of sync with InnoDB directory if .frm file does not exists. This change was required to be able to try to drop an InnoDB file when .frm doesn't exists. - Fixed bug in mi_delete_table() where the .MYD file would not be dropped if the .MYI file didn't exists. - Fixed memory leak in Mroonga when deleting non existing table - Fixed memory leak in Connect when deleting non existing table Bugs fixed introduced by the original version of this commit: MDEV-22826 Presence of Spider prevents tables from being force-deleted from other engines
118 lines
3.3 KiB
Plaintext
118 lines
3.3 KiB
Plaintext
create table t1(f1 int not null, f2 int not null, index idx(f2))engine=innodb;
|
|
create table t2(f1 int primary key, f2 int, index idx(f2))engine=innodb;
|
|
insert into t1 values(1, 2);
|
|
insert into t2 values(1, 2);
|
|
SET GLOBAL innodb_fast_shutdown = 0;
|
|
# restart: --innodb-force-recovery=4
|
|
select * from t1;
|
|
f1 f2
|
|
1 2
|
|
begin;
|
|
insert into t1 values(2, 3);
|
|
rollback;
|
|
alter table t1 add f3 int not null, algorithm=copy;
|
|
alter table t1 add f4 int not null, algorithm=inplace;
|
|
drop index idx on t1;
|
|
update t1 set f1=3 where f2=2;
|
|
create table t3(f1 int not null)engine=innodb;
|
|
drop table t3;
|
|
rename table t1 to t3;
|
|
rename table t3 to t1;
|
|
truncate table t1;
|
|
show tables;
|
|
Tables_in_test
|
|
t1
|
|
t2
|
|
# restart: --innodb-force-recovery=5
|
|
select * from t2;
|
|
f1 f2
|
|
1 2
|
|
insert into t2 values(2, 3);
|
|
ERROR HY000: Running in read-only mode
|
|
alter table t2 add f3 int not null, algorithm=copy;
|
|
ERROR HY000: Can't create table `test`.`t2` (errno: 165 "Table is read only")
|
|
alter table t2 add f3 int not null, algorithm=inplace;
|
|
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Running in read-only mode. Try ALGORITHM=COPY
|
|
drop index idx on t2;
|
|
ERROR HY000: Can't create table `test`.`t2` (errno: 165 "Table is read only")
|
|
update t2 set f1=3 where f2=2;
|
|
ERROR HY000: Running in read-only mode
|
|
create table t3(f1 int not null)engine=innodb;
|
|
ERROR HY000: Can't create table `test`.`t3` (errno: 165 "Table is read only")
|
|
drop table t3;
|
|
ERROR HY000: Table 't3' is read only
|
|
rename table t2 to t3;
|
|
ERROR HY000: Error on rename of './test/t2' to './test/t3' (errno: 165 "Table is read only")
|
|
truncate table t2;
|
|
ERROR HY000: Table 't2' is read only
|
|
drop table t2;
|
|
ERROR HY000: Table 't2' is read only
|
|
create schema db;
|
|
drop schema db;
|
|
show tables;
|
|
Tables_in_test
|
|
t1
|
|
t2
|
|
# restart: --innodb-force-recovery=6
|
|
select * from t2;
|
|
f1 f2
|
|
1 2
|
|
insert into t2 values(2, 3);
|
|
ERROR HY000: Table 't2' is read only
|
|
alter table t2 add f3 int not null, algorithm=copy;
|
|
ERROR HY000: Table 't2' is read only
|
|
alter table t2 add f3 int not null, algorithm=inplace;
|
|
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Running in read-only mode. Try ALGORITHM=COPY
|
|
drop index idx on t2;
|
|
ERROR HY000: Table 't2' is read only
|
|
update t2 set f1=3 where f2=2;
|
|
ERROR HY000: Table 't2' is read only
|
|
create table t3(f1 int not null)engine=innodb;
|
|
ERROR HY000: Can't create table `test`.`t3` (errno: 165 "Table is read only")
|
|
drop table t1;
|
|
ERROR HY000: Table 't1' is read only
|
|
rename table t2 to t3;
|
|
ERROR HY000: Error on rename of './test/t2' to './test/t3' (errno: 165 "Table is read only")
|
|
truncate table t2;
|
|
ERROR HY000: Table 't2' is read only
|
|
drop table t2;
|
|
ERROR HY000: Table 't2' is read only
|
|
show tables;
|
|
Tables_in_test
|
|
t1
|
|
t2
|
|
# restart: --innodb-force-recovery=2
|
|
select * from t2;
|
|
f1 f2
|
|
1 2
|
|
begin;
|
|
update t2 set f2=3;
|
|
connect con1,localhost,root,,;
|
|
# Force a redo log flush of the above uncommitted UPDATE
|
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
|
drop table t1;
|
|
disconnect con1;
|
|
connection default;
|
|
# Kill the server
|
|
# restart: --innodb-force-recovery=3
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
select * from t2;
|
|
f1 f2
|
|
1 3
|
|
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
|
select * from t2;
|
|
f1 f2
|
|
1 2
|
|
SET GLOBAL innodb_lock_wait_timeout=1;
|
|
insert into t2 values(1,2);
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
insert into t2 values(9,10);
|
|
# restart
|
|
select * from t2;
|
|
f1 f2
|
|
1 2
|
|
9 10
|
|
drop table t2;
|
|
show tables;
|
|
Tables_in_test
|