Home » Mysql » MySQL: Error dropping database (errno 13; errno 17; errno 39)

MySQL: Error dropping database (errno 13; errno 17; errno 39)

Posted by: admin November 1, 2017 Leave a comment

Questions:

I failed to drop a database:

mysql> drop database mydb;
ERROR 1010 (HY000): Error dropping database (can't rmdir './mydb', errno: 39)

Directory db/mydb exists in mysql tree but has no table:

# ls -l db/mydb
-rw-rw---- mysql mysql HIS_STAT.MYD
-rw-rw---- mysql mysql HIS_STAT.MYI

What should I do?

Answers:

Errno 13

MySQL has no write permission on the parent directory in which the mydb folder resides.

Check it with

ls -la /path/to/data/dir/         # see below on how to discover data dir
ls -la /path/to/data/dir/mydb   

Errno 39

This code means “directory not empty”. The directory contains some hidden files MySQL knows nothing about. For non-hidden files, see Errno 17. The solution is the same.

Errno 17

This code means “file exists”. The directory contains some MySQL file that MySQL doesn’t feel about deleting. Such files could have been created by a SELECT ... INTO OUTFILE "filename"; command where filename had no path. In this case, the MySQL process creates them in its current working directory, which (tested on MySQL 5.6 on OpenSuSE 12.3) is the data directory of the database, e.g. /var/lib/mysql/data/nameofdatabase.

Reproducibility:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1676
Server version: 5.6.12-log openSUSE package
[ snip ]    

mysql> CREATE DATABASE pippo;
Query OK, 1 row affected (0.00 sec)

mysql> USE pippo;
Database changed
mysql> SELECT version() INTO OUTFILE 'test';
Query OK, 1 row affected (0.00 sec)

mysql> DROP DATABASE pippo;
ERROR 1010 (HY000): Error dropping database (can't rmdir './pippo/', errno: 17)

-- now from another console I delete the "test" file, without closing this connection
-- and just retry. Now it works.

mysql> DROP DATABASE pippo;
Query OK, 0 rows affected (0.00 sec)

Move the file(s) outside (or delete if not needed) and retry. Also, determine why they were created in the first place – it could point to a bug in some application. Or worse: see below…

UPDATE: Error 17 as exploit flag

This happened on a Linux system with WordPress installed. Unfortunately the customer was under time constraints and I could neither image the disk or do a real forensics round – I reinstalled the whole machine and WordPress got updated in the process, so I can only say that I’m almost certain they did it through this plugin.

Symptoms: the mysql data directory contained three files with extension PHP. Wait, what?!? — and inside the files there was a bulk of base64 code which was passed to base64_decode, gzuncompress and [eval()][2]. Aha. Of course these were only the first attempts, the unsuccessful ones. The site had been well and truly pwn3d.

So if you find a file in your mysql data dir that’s causing an Error 17, check it with file utility or scan it with an antivirus. Or visually inspect its contents. Do not assume it’s there for some innocuous mistake.

The victim in this case (he had some friend “do the maintenance”) would never have guessed he’d been hacked until a maintenance/update/whatever script ran a DROP DATABASE (do not ask me why – I’m not sure even I want to know) and got an error. From the CPU load and the syslog messages, I’m fairly positive that the host had become a spam farm.

Yet another Error 17

If you rsync or copy between two MySQL installations of the same version but different platform or file systems such as Linux or Windows (which is discouraged, and risky, but many do it nonetheless), and specifically with different case sensitivity settings, you can accidentally end up with two versions of the same file (either data, index, or metadata); say Customers.myi and Customer.MYI. MySQL uses one of them and knows nothing about the other (which could be out of date and lead to a disastrous sync). When dropping the database, which also happens in many a mysqldump ... | ... mysql backup schemes, the DROP will fail because that extra file (or those extra files) exists. If this happens, you should be able to recognize the obsolete file(s) that need manual deletion from the file time, or from the fact that their case scheme is different from the majority of the other tables.

Finding the data-dir

In general, you can find the data directory by inspecting the my.cnf file (/etc/my.cnf, /etc/sysconfig/my.cnf, /etc/mysql/my.cnf on Linux; my.ini in the MySQL program files directory in Windows), under the [mysqld] heading, as datadir.

Alternatively you can ask it to MySQL itself:

mysql> SHOW VARIABLES WHERE Variable_name LIKE '%datadir%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| datadir       | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.00 sec)

Questions:
Answers:

In my case it was due to ‘lower_case_table_names’ parameter.

The error number 39 thrown out when I tried to drop the databases which consists upper case table names with lower_case_table_names parameter is enabled.

This is fixed by reverting back the lower case parameter changes to the previous state.