[MDEV-17859] Operating system errors in file operations after failed CREATE Created: 2018-11-28  Updated: 2018-12-03  Resolved: 2018-11-28

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - InnoDB
Affects Version/s: 10.3
Fix Version/s: 10.4.1, 10.2.20, 10.3.12

Type: Bug Priority: Critical
Reporter: Elena Stepanova Assignee: Marko Mäkelä
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Problem/Incident
is caused by MDEV-17816 InnoDB: Failing assertion: trx->dict_... Closed
Relates
relates to MDEV-17432 Assertion `lock_trx_has_sys_table_loc... Closed

 Description   

Note: the test case fails for me every time on a non-debug build, but there is still some concurrency involved in the scenario, so it can be different on other machines. I couldn't so far reproduce the problem on a debug or ASAN-debug build.

--source include/have_innodb.inc
 
CREATE SEQUENCE s1 ENGINE=InnoDB;
CREATE TABLE t1 (i INT) ENGINE=InnoDB;
 
--connect (con1,localhost,root,,test)
 
BEGIN;
SELECT * FROM mysql.innodb_table_stats;
 
--connection default
CREATE SEQUENCE s2 ENGINE=InnoDB;
 
--connection con1
--send
  SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS;
 
--connection default
FLUSH TABLES;
 
--connection con1
--reap
 
--connection default
 
--error ER_TABLE_EXISTS_ERROR,ER_TABLESPACE_EXISTS
CREATE TABLE s2 LIKE t1;
--error ER_TABLE_EXISTS_ERROR
CREATE TABLE s2 LIKE s1;
 
--connection con1
SELECT * FROM t1;
 
--connection default
SET lock_wait_timeout= 1;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE t1 ADD COLUMN a INTEGER;
 
# Cleanup
--disconnect con1
DROP SEQUENCE s1, s2;
DROP TABLE t1;

10.3 RelWithDebInfo babb000a36f7

2018-11-28 10:37:14 9 [ERROR] InnoDB: Operating system error number 17 in a file operation.
2018-11-28 10:37:14 9 [ERROR] InnoDB: Error number 17 means 'File exists'
2018-11-28 10:37:14 9 [Note] InnoDB: Some operating system error numbers are described at https://mariadb.com/kb/en/library/operating-system-error-codes/
2018-11-28 10:37:14 9 [Note] InnoDB: The file './test/s2.ibd' already exists though the corresponding table did not exist in the InnoDB data dictionary. You can resolve the problem by removing the file.
2018-11-28 10:37:14 9 [ERROR] InnoDB: Cannot create file './test/s2.ibd'
2018-11-28 10:37:14 9 [ERROR] InnoDB: Failed to find tablespace for table `test`.`s2` in the cache. Attempting to load the tablespace with space id 7
2018-11-28 10:37:14 9 [ERROR] InnoDB: Refusing to load './test/s2.ibd' (id=9, flags=0x21); dictionary contains id=7, flags=0x21
2018-11-28 10:37:14 9 [ERROR] InnoDB: Operating system error number 2 in a file operation.
2018-11-28 10:37:14 9 [ERROR] InnoDB: The error means the system cannot find the path specified.
2018-11-28 10:37:14 9 [ERROR] InnoDB: Could not find a valid tablespace file for ``test`.`s2``. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue.
2018-11-28 10:37:14 9 [Note] InnoDB: Deleting ./test/s2.ibd
2018-11-28 10:37:14 0 [ERROR] InnoDB: Operating system error number 2 in a file operation.
2018-11-28 10:37:14 0 [ERROR] InnoDB: The error means the system cannot find the path specified.
2018-11-28 10:37:14 0 [ERROR] InnoDB: File ./test/s2.ibd: 'open' returned OS error 71.
2018-11-28 10:37:14 0x7f8dae7fc700  InnoDB: Assertion failure in file /data/src/10.3/storage/innobase/fil/fil0fil.cc line 671
InnoDB: Failing assertion: success
 
#5  0x000055ace8148000 in ut_dbg_assertion_failed (expr=expr@entry=0x55ace8a52d29 "success", file=file@entry=0x55ace8a74828 "/data/src/10.3/storage/innobase/fil/fil0fil.cc", line=line@entry=671) at /data/src/10.3/storage/innobase/ut/ut0dbg.cc:60
#6  0x000055ace87c8448 in fil_node_open_file (node=node@entry=0x7f8d68073de0) at /data/src/10.3/storage/innobase/fil/fil0fil.cc:671
#7  0x000055ace87c898f in fil_node_prepare_for_io (node=node@entry=0x7f8d68073de0, space=space@entry=0x7f8d680907e0) at /data/src/10.3/storage/innobase/fil/fil0fil.cc:4080
#8  0x000055ace87c9f13 in fil_io (type=..., sync=sync@entry=false, page_id=..., page_size=..., byte_offset=byte_offset@entry=0, len=16384, buf=0x7f8db6670000, message=0x7f8db6150a68, ignore_missing_space=false) at /data/src/10.3/storage/innobase/fil/fil0fil.cc:4335
#9  0x000055ace876c039 in buf_dblwr_write_block_to_datafile (bpage=0x7f8db6150a68, sync=sync@entry=false) at /data/src/10.3/storage/innobase/buf/buf0dblwr.cc:929
#10 0x000055ace876dd8d in buf_dblwr_flush_buffered_writes () at /data/src/10.3/storage/innobase/buf/buf0dblwr.cc:1075
#11 0x000055ace87784cf in buf_flush_end (flush_type=<optimized out>, buf_pool=0x55aceb005f90) at /data/src/10.3/storage/innobase/buf/buf0flu.cc:1972
#12 buf_flush_do_batch (buf_pool=<optimized out>, type=<optimized out>, min_n=<optimized out>, lsn_limit=<optimized out>, n=<optimized out>) at /data/src/10.3/storage/innobase/buf/buf0flu.cc:2041
#13 0x000055ace87788db in buf_flush_lists (min_n=200, lsn_limit=lsn_limit@entry=18446744073709551615, n_processed=0x7f8dae7fbc90) at /data/src/10.3/storage/innobase/buf/buf0flu.cc:2145
#14 0x000055ace877bbb7 in buf_flush_page_cleaner_coordinator () at /data/src/10.3/storage/innobase/buf/buf0flu.cc:3297
#15 0x00007f8dc2601494 in start_thread (arg=0x7f8dae7fc700) at pthread_create.c:333
#16 0x00007f8dc0c0293f in clone () from /lib/x86_64-linux-gnu/libc.so.6

The scenario is not applicable to 10.2 because sequences are involved.



 Comments   
Comment by Marko Mäkelä [ 2018-11-28 ]

With the following tentative follow-up fix to MDEV-17816, the test no longer crashes for me:

diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 9725375ebbb..80fa8e6d7dd 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -12358,9 +12358,11 @@ int create_table_info_t::create_table(bool create_fk)
 			so that rollback can possibly rename back a table
 			that could have been renamed before
 			the failed creation. */
-			m_trx->error_state = DB_SUCCESS;
-			row_drop_table_for_mysql(m_table_name, m_trx,
-						 SQLCOM_TRUNCATE);
+			if (m_table->cached) {
+				m_trx->error_state = DB_SUCCESS;
+				row_drop_table_for_mysql(m_table_name, m_trx,
+							 SQLCOM_TRUNCATE);
+			}
 			trx_rollback_to_savepoint(m_trx, NULL);
 
 			m_trx->error_state = DB_SUCCESS;
@@ -12590,9 +12592,11 @@ ha_innobase::create(
 		/* Drop the being-created table before rollback,
 		so that rollback can possibly rename back a table
 		that could have been renamed before the failed creation. */
-		trx->error_state = DB_SUCCESS;
-		row_drop_table_for_mysql(info.table_name(), trx,
-					 SQLCOM_TRUNCATE, true);
+		if (info.table() && info.table()->cached) {
+			trx->error_state = DB_SUCCESS;
+			row_drop_table_for_mysql(info.table_name(), trx,
+						 SQLCOM_TRUNCATE, true);
+		}
 		trx_rollback_for_mysql(trx);
 		row_mysql_unlock_data_dictionary(trx);
 		if (own_trx) {
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 7bec858b5af..cb3de206890 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -729,6 +729,9 @@ class create_table_info_t
 	const char* table_name() const
 	{ return(m_table_name); }
 
+	/** @return the created table */
+	const dict_table_t* table() const { return m_table; }
+
 	THD* thd() const
 	{ return(m_thd); }
 

Comment by Marko Mäkelä [ 2018-11-28 ]

The problem was that in MDEV-17816, the error handling of CREATE TABLE was changed so that the table by that name would be dropped. This is obviously wrong if such a table already existed in InnoDB.

The solution is to drop the incompletely created table only if the table was actually created.

A proper solution would be to write undo log for table creation, so that normal rollback would take care of dropping the table.

Generated at Thu Feb 08 08:39:39 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.