I am attempting use MySQL to create two tables on separate drives so I can do some bench marking. I found this documentation on the Data Directory command which seems to do exactly what I need, but it is not working for me. Here is what I get:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.00 sec)
mysql> create table t1 (id int primary key, name text) data directory = '/media/ssd';
Query OK, 0 rows affected (0.03 sec)
However the table file is made in the default /var/lib/mysql/test and /media/ssd remains empty.
$ sudo ls /var/lib/mysql/test
db.opt t1.frm t1.ibd
$ ls -l /media/ssd
total 0
I have also tried other locations like /home and I get the same result so I don't believe it is a drive mounting issue. I also set the /media/ssd permissions to 777.
Any ideas why it is creating the table in the default location?
If need be can I just move the .idb file to my desired location and put a .isl in it's place?
Related
I have a weird scenario where a technician deleted the .frm and .idb files for a table from one of my servers, fortunately it was a non critical table. I'm trying to recreate the table however when trying to use the CREATE TABLE, DROP TABLE or ALTER TABLE I get errors cos the tablespace still exists. I'm not really able to move the good tables to a new schema, drop the old schema then recreate the table that way as there are critical tables still in the schema which cannot be taken offline. Any thoughts on how I get rid of this "broken" table?
I created a test table:
mysql> use test;
mysql> create table test ( id serial primary key );
mysql> insert into test () values ();
Check that the files exist in my datadir:
$ cd /usr/local/var/mysql/test
$ ls
db.opt test.frm test.ibd
Do the unthinkable!
$ rm test.*
Now I have a catch-22 situation:
mysql> show tables;
Empty set (0.00 sec)
mysql> create table test (id serial primary key);
ERROR 1050 (42S01): Table 'test' already exists
mysql> drop table test;
ERROR 1051 (42S02): Unknown table 'test.test'
What to do?
mysql> create schema recovery;
mysql> create table recovery.test ( id serial primary key );
mysql> system cp /usr/local/var/mysql/recovery/test.frm /usr/local/var/mysql/test/
The .frm file stores table metadata in MySQL 5.x. Now that I have a .frm file, MySQL lets me query the table.
mysql> select * from test;
+----+
| id |
+----+
| 1 |
+----+
That's funny — how does it know about that row of data? Didn't I rm the .ibd file?
Answer: Files are not truly deleted while a process still has a filehandle open to it. Since I have not restarted the MySQL Server process, the .ibd tablespace file still exists, even though I unlinked it from the datadir!
Anyway, I can now drop the table. This removes the .frm and .ibd AND closes the filehandles to them, so they are truly deleted from the filesystem.
mysql> drop table test;
Query OK, 0 rows affected (0.01 sec)
And finally I can now create a new table of the same name, even with different columns.
mysql> create table test ( bar int primary key );
Query OK, 0 rows affected (0.02 sec)
When I try to access it:
But check this out:
I'm pretty sure that it is because I delete the databases without dropping it first. Can any one help me?
It's possible that maybe information schema doesn't have the proper data? (or does)
Try running the following, and it should give you your answer:
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'Ascii';
SHOW TABLES most likely uses the file structure.
If you run this query:
mysql> SHOW VARIABLES LIKE 'datadir';
+---------------+-----------------------+
| Variable_name | Value |
+---------------+-----------------------+
| datadir | /usr/local/mysql/var/ |
+---------------+-----------------------+
1 row in set (0.00 sec)
Then do ls /usr/local/mysql/var/Ascii/, you should be able to see the table files. There should be an .frm, .MYD, and .MYI
Can someone explain me, what is happening here,
I created one table in MyISAM.
show tables -- shows it.
select command gives empty table from the table.
I delete the myisam files from location.
show tables -- does not show it.
Ok till now.
Now, still I am able to insert into table, and able to select from the table [can it happen?? how??]
Again, drop table says table does not exist.
and after this, select command says table does not exist.
Question is "where did it get inserted, and from where it is selecting the data; and after drop table call, where did it vanish?"
Server version: 5.5.38-log MySQL Community Server (GPL)
The overall sequence ..
MySQL [test]> CREATE TABLE test (id int(11) DEFAULT NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.05 sec)
MySQL [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| test |
+----------------+
1 row in set (0.00 sec)
MySQL [test]> select * from test;
Empty set (0.00 sec)
~~~~~~~~~~~~~~~~~~~~~~~~~
[root#localhost test]# pwd
/var/lib/mysql/test
[root#localhost test]# ll
total 16
-rw-rw---- 1 mysql mysql 8556 Dec 23 14:08 test.frm
-rw-rw---- 1 mysql mysql 0 Dec 23 14:08 test.MYD
-rw-rw---- 1 mysql mysql 1024 Dec 23 14:08 test.MYI
[root#localhost test]# rm -f *
[root#localhost test]# ll
total 0
[root#localhost test]#
~~~~~~~~~~~~~~~~~~~~~~~~~
MySQL [test]> show tables;
Empty set (0.00 sec)
MySQL [test]> insert into test values (1234);
Query OK, 1 row affected (0.00 sec)
MySQL [test]> select * from test;
+------+
| id |
+------+
| 1234 |
+------+
1 row in set (0.00 sec)
MySQL [test]> drop table test;
ERROR 1051 (42S02): Unknown table 'test'
MySQL [test]> select * from test;
ERROR 1146 (42S02): Table 'test.test' doesn't exist
On Unix, if you remove a file that another process has opened, it just removes the name from the directory, but the file still exists on disk, and the other process can continue to access it. It doesn't really go away until all processes close the file.
The MySQL daemon presumably opens the files related to a table the first time it's accessed, and then keeps the file open for as long as it can. So once it has accessed a table, removing the filename doesn't affect its operations on the contents of the table.
However, DML operations like show tables and drop tables work by accessing the directory, not the open files, so they notice the change. Then all the internal data structures are sync'ed with the filesystem.
I have got two servers both running a MySQL instance. The first one, server1, is running MySQL 5.0.22. The other one, server2, is running MySQL 5.1.58.
When I create a memory table on server1 and I add a row its size is instantly 8,190.0 KiB.
When I create a memory table on server2 and I add a row its size is still only some bytes, though.
Is this caused by the difference in MySQL version or (hopefully) is this due to some setting I can change?
EDIT:
I haven't found the reason for this behaviour yet, but I did found a workaround. So, for future references, this is what fixed it for me:
All my memory tables are made once and are read-only from thereon. When you specify to MySQL the maximum number of rows your table will have, its size will shrink. The following query will do that for you.
ALTER TABLE table_name MAX_ROWS = N
Factor of 2?
OK, the problem likely is caused by the UTF-8 vs latin1
:- http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
You can check the database connection, database default character set for both servers.
here is the testing I have just done :-
mysql> create table test ( name varchar(10) ) engine
-> =memory;
Query OK, 0 rows affected (0.03 sec)
mysql> show create table test;
+-------+------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`name` varchar(10) DEFAULT NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1 |
+-------+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> insert into test values ( 1 );
mysql> set names utf8;
Query OK, 0 rows affected (0.01 sec)
mysql> create table test2 ( name varchar(10) ) engine =memory default charset = utf8;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test2 values ( convert(1 using utf8) );
Query OK, 1 row affected (0.01 sec)
mysql> select table_name, avg_row_length from information_schema.tables where TABLE_NAME in( 'test2', 'test');
+------------+----------------+
| table_name | avg_row_length |
+------------+----------------+
| test | 12 |
| test2 | 32 |
+------------+----------------+
2 rows in set (0.01 sec)
Is there a way to attach a piece of metadata to a MySQL database? I'm trying to write code to automatically update the database schema whenever a code upgrade requires it. This requires the storage of a single integer value -- the schema version. I could of course create a whole table for it, but that seems like overkill for just a simple number.
You can use table comments to store the version:
ALTER TABLE table1 COMMENT = '1.4';
You'll have to regex to get the comment from this:
SHOW CREATE TABLE table1;
/COMMENT='(.*)'/
To answer the question as titled, that is for metadata for the entire database and not individual tables, there are a couple of choices, depending on the privileges that you have.
The most direct route is to create a stored function, which requires the CREATE ROUTINE privilege. e.g.
mysql> CREATE FUNCTION `mydb`.DB_VERSION() RETURNS VARCHAR(15)
RETURN '1.2.7.2861';
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT `mydb`.DB_VERSION();
+--------------+
| DB_VERSION() |
+--------------+
| 1.2.7.2861 |
+--------------+
1 row in set (0.06 sec)
If your privileges limit you to only creating tables, you can create a simple table and put the metadata as default values. There’s no need to store any data in the table.
mysql> CREATE TABLE `mydb`.`db_metadata` (
`version` varchar(15) not null default '1.2.7.2861');
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW COLUMNS FROM `mydb`.`db_metadata`;
+---------+-------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+------------+-------+
| version | varchar(15) | NO | | 1.2.7.2861 | |
+---------+-------------+------+-----+------------+-------+
1 row in set (0.00 sec)