Bug #29322 create table partition datadir to existing file => crash
Submitted: 24 Jun 2007 12:31 Modified: 6 Jul 2007 10:30
Reporter: Martin Friebe (Gold Quality Contributor) (OCA) Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:5.1.20bk OS:FreeBSD
Assigned to: Georgi Kodinov CPU Architecture:Any
Tags: crash, data directory, partition, qc

[24 Jun 2007 12:31] Martin Friebe
Description:
Create a table with partitions and specify a data directory for the partition, that exists but can not be used (file exists).

Mysql will fail (as expected), because the partition MYD file can not be created.

But Mysql does not clean up. Parts of the table have been created and are left behind (in memory and on disk)

Attempting to delete the table does crash the server.

since the incomplete table exists on disk, it will exists even after a data restart. it will still crash if attempted to delete.

How to repeat:

create database db1;
create database db2;

use db1;
drop table if exists t1; 
CREATE TABLE t1 (a INT)  PARTITION BY RANGE ( a )
( PARTITION p0 VALUES LESS THAN (10)  ,
 PARTITION p1 VALUES LESS THAN (20)   
);

use db2;
drop table if exists t1; 
CREATE TABLE t1 (b INT)  PARTITION BY RANGE ( b )
( PARTITION p0 VALUES LESS THAN (10)  DATA DIRECTORY = '/mysqldata/db1/',
 PARTITION p1 VALUES LESS THAN (20)   
);
#Error (Code 1):
#Can't create/write to file '/mysqldata/db1/t1#P#p0.MYD' (Errcode: 17)

show tables;
desc t1;
drop table t1; # crash

#restart mysqld
use db2;
drop table t1; # crash

Suggested fix:
- fix the "create table" to clean up

- fix the "drop table" not to crash, if it encounters a broken table

#0  0x2841231b in pthread_testcancel () from /usr/lib/libpthread.so.1
#1  0x283fd1dd in pthread_kill () from /usr/lib/libpthread.so.1
#2  0x0821b49a in write_core (sig=11) at stacktrace.c:231
#3  0x080ed377 in handle_segfault (sig=11) at mysqld.cc:2274
#4  0x284018fc in sigaction () from /usr/lib/libpthread.so.1
#5  0xbfbfff94 in ?? ()
#6  0x0000000b in ?? ()
#7  0xbfaba510 in ?? ()
#8  0xbfaba250 in ?? ()
#9  0x00000000 in ?? ()
#10 0x28401560 in sigaction () from /usr/lib/libpthread.so.1
#11 0x081cccc2 in ha_partition::print_error (this=0x8d91250, error=2, errflag=0) at ha_partition.cc:5231
#12 0x081c014a in ha_delete_table (thd=0x8d79000, table_type=0x8d9107b, path=0xbfabc1a4 "./db2/t1", db=0x8d91248 "db2", alias=0x8d91078 "t1",
    generate_warning=true) at handler.cc:1471
#13 0x081d2b2e in mysql_rm_table_part2 (thd=0x8d79000, tables=0x8d910a0, if_exists=false, drop_temporary=false, drop_view=false,
    dont_log_query=false) at sql_table.cc:1671
#14 0x081d2441 in mysql_rm_table (thd=0x8d79000, tables=0x8d910a0, if_exists=0 '\0', drop_temporary=0 '\0') at sql_table.cc:1437
#15 0x080fb1cb in mysql_execute_command (thd=0x8d79000) at sql_parse.cc:2913
#16 0x081004d7 in mysql_parse (thd=0x8d79000, inBuf=0x8d91010 "drop table t1", length=3215706612, found_semicolon=0xbfabcacc)
    at sql_parse.cc:5388
#17 0x080f7216 in dispatch_command (command=COM_QUERY, thd=0x8d79000, packet=0x8d83001 "drop table t1", packet_length=14) at sql_parse.cc:909
#18 0x080f69fc in do_command (thd=0x8d79000) at sql_parse.cc:668
#19 0x080f56a7 in handle_one_connection (arg=0x0) at sql_connect.cc:1094
#20 0x2840a902 in pthread_mutexattr_init () from /usr/lib/libpthread.so.1
#21 0x00000000 in ?? ()
[24 Jun 2007 12:33] Martin Friebe
to reproduce, please replace /mysqldata/ with the correct data path.
 show variables like 'datadir';
[24 Jun 2007 12:58] Valeriy Kravchuk
Thank you for a problem report. Sorry, but I've got no crash with latest 5.0.20-debug on Linux:

openxs@linux:~/dbs/5.1> bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.20-beta-debug Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create database db1;
Query OK, 1 row affected (0.04 sec)

mysql> create database db2;
Query OK, 1 row affected (0.00 sec)

mysql>
mysql> use db1;
Database changed
mysql> drop table if exists t1;
Query OK, 0 rows affected, 1 warning (0.01 sec)

CREATE TABLE t1 (a INT)  PARTITION BY RANGE ( a )
mysql> CREATE TABLE t1 (a INT)  PARTITION BY RANGE ( a )
    -> ( PARTITION p0 VALUES LESS THAN (10)  ,
    ->  PARTITION p1 VALUES LESS THAN (20)
    -> );
use db2;
drop table if exists t1;
CREATE TABLE t1 (b INT)  PARTITION BY RANGE ( b )
( PARTITION p0 VALUES LESS THAN (10)  DATA DIRECTORY = 'Query OK, 0 rows affected (0.02 sec)

mysql>
mysql> use db2;
Database changed
mysql> drop table if exists t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE t1 (b INT)  PARTITION BY RANGE ( b )
    -> ( PARTITION p0 VALUES LESS THAN (10)  DATA DIRECTORY = '/home/openxs/dbs/5.1/var/db1/',
    -> PARTITION p1 VALUES LESS THAN (20)
    -> );
ERROR 1 (HY000): Can't create/write to file '/home/openxs/dbs/5.1/var/db1/t1#P#p0.MYD' (Errcode: 17)
mysql> show tables;
Empty set (0.01 sec)

mysql> desc t1;
ERROR 1146 (42S02): Table 'db2.t1' doesn't exist

mysql> drop table t1;
ERROR 1051 (42S02): Unknown table 't1'

What I did wrong above? Maybe, I have to check non-debug build...
[24 Jun 2007 14:38] MySQL Verification Team
stack does trace look like the bug I reported, bug #28490
[24 Jun 2007 18:29] Martin Friebe
I agree with Shane, the "drop table" is probably the same as bug #28490. The problem is a not fully created table.

The error with not cleaning up the table, if creation fails, seams myisam related. (so the sql needs a "engine myisam" in both create statements).

I was able to trace what happens in the source.

Looking at the 2nd "create table" (in db2, the one that is not cleaned):

The error msg is createt in mysys/my_symlink2.c function my_create_with_symlink line 59:
    if (!access(filename,F_OK))
    {
      my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
      DBUG_RETURN(-1);
    }
Note: this does NOT set "my_errno"

my_create_with_symlink was called from storage/myisam/mi_create_c function mi_create line 694:
      if ((dfile=
	   my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
				  MYF(MY_WME | create_flag))) < 0)
	goto err;
....
line 834
err:
  pthread_mutex_unlock(&THR_LOCK_myisam);
  save_errno=my_errno;
....
  DBUG_RETURN(my_errno=save_errno);		/* return the fatal errno */

So mi_create returns 0 / no error.

This is passed on (as success)
ha_myisam.cc ha_myisam::create()
ha_partition.cc ha_partition::del_ren_cre_table()

and in sql/ha_partition.cc ha_partition::create line 556
  if (del_ren_cre_table(t_name, NULL, table_arg, create_info))
  {
    handler::delete_table(t_name);
    DBUG_RETURN(1);
  }

the "if" receives 0 (zero) from the call, and does not call handler::delete_table.

However, if you manage to get such an unfinished table, it may be that fixing the above, will only make the crash happen earlier.
Since the crash in "drop table" also happens in handler::delete_table.

---
Outside of the above bug my_create_with_symlink is also called in storage/myisam/mi_create_c function mi_create line 639:
  if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
				    MYF(MY_WME | create_flag))) < 0)
    goto err;

Since it is in the same method, it is probably experiencing the same issue.
[27 Jun 2007 23:23] Sveta Smirnova
Thank you for the report.

Verified as described using last BK sources.

Bug is repeatable only on FreeBSD. Linux and Mac versions are not affected.
[6 Jul 2007 10:30] Georgi Kodinov
Tried with the latest 5.1bk (5.1.21beta). The server don't crash on Linux (Fedora7), FreeBSD 6 32bit (the box where sveta reproduced the effect with 5.1.19) and 64 bit. 
I got:
+ create database db1;
+ create database db2;
+ use db1;
+ drop table if exists t1;
+ Warnings:
+ Note  1051    Unknown table 't1'
+ CREATE TABLE t1 (a INT)  PARTITION BY RANGE ( a )
+ ( PARTITION p0 VALUES LESS THAN (10)  ,
+ PARTITION p1 VALUES LESS THAN (20)   
+ );
+ use db2;
+ drop table if exists t1;
+ Warnings:
+ Note  1051    Unknown table 't1'
+ CREATE TABLE t1 (b INT)  PARTITION BY RANGE ( b ) ( PARTITION p0 VALUES LESS THAN (10)  DATA DIRECTORY = '/usr/home/mysqldev/gkodinov/mysql-5.1.21-beta-pb267/mysql-test/var/master-data/db1/', PARTITION p1 VALUES LESS THAN (20)   );
+ ERROR HY000: Can't create/write to file '/usr/home/mysqldev/gkodinov/mysql-5.1.21-beta-pb267/mysql-test/var/master-data/db1/t1#P#p0.MYD' (Errcode: 17)
+ show tables;
+ Tables_in_db2
+ desc t1;
+ ERROR 42S02: Table 'db2.t1' doesn't exist
+ drop table t1;
+ ERROR 42S02: Unknown table 't1'
+ use db2;
+ drop table t1;
+ ERROR 42S02: Unknown table 't1'