Earlier today, I asked for an easy way to store a version number for the SQL table layout you are using in SQLite, and got the suggestion to use PRAGMA user_version. As there is no such thing as a Pragma in MySQL, I was wondering on how you would go about this in MySQL (Except for creating a table named "META" with a column "DB-Scheme-Version").
Just to repeat what I said in the linked question: I'm not looking for a way to find out which version of MySQL is installed, but to save a version nuber that tells me what version of my MySQL-Scheme I am using, without checking every table via script.
I also saw this question, but it only allows me to version single tables. Is there something similar or, preferably, easier, for whole Databases (Since it would be no fun to query every single table seperately)? Thanks in advance.
MySQL's SET GLOBAL would probably work, but I prefer a solution that does not reset itself every time the server reboots and does not require SUPER Privilege and / or access to the configuration file to use. To put it short: It should work with a standard MySQL-Database that you get when you rent a small webhosting package, not the ones you get if you rent a full server, as you tend to have more access to those.
There are a couple of choices, depending on the privileges that you have. The higher privileges you have, the more “elegant” the solution.
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 version in a default value:
mysql> CREATE TABLE `mydb`.`db_version` (
`version` varchar(15) not null default '1.2.7.2861');
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW COLUMNS FROM `mydb`.`db_version`;
+---------+-------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+------------+-------+
| version | varchar(15) | NO | | 1.2.7.2861 | |
+---------+-------------+------+-----+------------+-------+
1 row in set (0.00 sec)
Related
I am using Mysql and by mistake deleted very important details.Is there a way how to recover deleted records in Mysql?
I know this is not really what you are asking but I find it important that you know this.
The system I suggest is called soft delete. It works as follow:
Make a new column in your table (for ex the table people):
ID
Name
Deleted
1
Bob
0
2
Frank
1
3
Alice
0
With 0 as undeleted and 1 as deleted in last column with the type BOOLEAN. Name and ID are respectively a NVARCHAR and an INT.
If you want delete a record, you don't delete it with a DELETE statement but update it like this:
UPDATE people SET Deleted = 1 WHERE ID = 1
Result:
ID
Name
Deleted
1
Bob
1
2
Frank
1
3
Alice
0
You know ID's 1 and 2 are deleted because the boolean in column Deleted is on 1. Alice with ID 3 is not deleted because the boolean is on 0.
The pro of this system is that you can recover data with only one statement!
UPDATE people SET Deleted = 0 WHERE Deleted = 1
Result:
ID
Name
Deleted
1
Bob
0
2
Frank
0
3
Alice
0
Now all record are recovered because the boolean in column Deleted is on 0.
If you use DELETE statement, it is impossible to recover all records! They are deleted for always and you can never recover it if you are using the DELETE statements. You can only use a backup file for recover it but has also contra's like:
It's an old backup file,
I've forget to make one,
I don't know how you can make it,
I've lost it,
...
By soft delete you change only one column and you have your data back.
Edit:
The contra of the system is that (like you have said) the data is not exactly remove from your database. It's only a column you change from 0 to 1. But if you know that you can make money from data... is this another story.
If you want to delete it exactly you can use a DELETE statement.
Do you have binlog files from the date where you insert these records ?
Then you can get the inserts and put it back
mysql> use employees;
Database changed
mysql> show create table employees;
| employees | CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` enum('M','F') NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 1000 |
+----------+
1 row in set (0.00 sec)
mysql> delete from employees;
mysql> flush table employees with read lock;
Query OK, 0 rows affected (0.01 sec)
we can directly scan the table .ibd file ,and find the deleted records:
select add .ibd from menu start
input the deleted table's ibd location
right click the ibd file , scan it
click the first page node , and input create table sql
choose the right mysql version , and page format (dynamic in most version)
select the Deleted Data Tab , then you can check deleted records and export them into MYSQLDUMP format SQL file.
You can also use conventional recovery mode in this case.
https://youtu.be/dVMO0YYcJoo
For InnoDB tables, if binary logs are enabled, one could use:
mysqlbinlog path_to_binary_log_file > query_log.sql
If binary logs are not enabled, there is a recovery tool provided by Percona which may help.
Created a script to automate the steps from the Percona tool which recovers the deleted rows (if exist) and provides SQL queries to load the data back into database.
Please note:
The time between the deletion of rows and the database stop is
crucial. If pages are reused you can’t recover the data.
PS: the DBRecover Tool by #ParnassusData is cool and much easier IMO
On my development server I have a column indexed with a cardinality of 200.
The table has about 6 million rows give or take and I have confirmed it is an identical row count on the production server.
However the production servers index has a cardinality of 31938.
They are both mysql 5.5 however my dev server is Ubuntu server 13.10 and the production server is Windows server 2012.
Any ideas on what would cause such a difference in what should be the exact same data?
The data was loaded into the production server from a MySQL dump of the dev server.
EDIT: Its worth noting that I have queries that take about 15 minutes to run on my dev server that seem to run forever on the production server due to what i believe to be these indexing issues. Different amounts of rows are being pulled within sub-queries.
Mysql checksums might help you verify that the tables are the same
-- a table
create table test.t ( id int unsigned not null auto_increment primary key, r float );
-- some data ( 18000 rows or so )
insert into test.t (r) select rand() from mysql.user join mysql.user u2;
-- a duplicate
create table test.t2 select * from test.t;
-- introduce a difference somewhere in there
update test.t2 set r = 0 order by rand() limit 1;
-- and prove the tables are different easily:
mysql> checksum table test.t;
+--------+------------+
| Table | Checksum |
+--------+------------+
| test.t | 2272709826 |
+--------+------------+
1 row in set (0.00 sec)
mysql> checksum table test.t2
-> ;
+---------+-----------+
| Table | Checksum |
+---------+-----------+
| test.t2 | 312923301 |
+---------+-----------+
1 row in set (0.01 sec)
Beware the checksum locks tables.
For more advanced functionality, the percona toolkit can both checksum and sync tables (though it's based on master/slave replication scenarios so it might not be perfect for you).
Beyond checksumming, you might consider looking at REPAIR OR OPTIMIZE.
I recently encountered a problem caused by a typo in the database creation script, whereby a column in the database was created as varchar(0) instead of varchar(20).
I expected that I would have gotten an error for 0-length string field, but I didn't. What is the purpose of varchar(0) or char(0) as I wouldn't be able to store any data in this column anyway.
It's not allowed per the SQL-92 standard, but permitted in MySQL. From the MySQL manual:
MySQL permits you to create a column of type CHAR(0). This is useful primarily when you have to be compliant with old applications that depend on the existence of a column but that do not actually use its value. CHAR(0) is also quite nice when you need a column that can take only two values: A column that is defined as CHAR(0) NULL occupies only one bit and can take only the values NULL and '' (the empty string).
Just checked MySQL, it's true that it allows zero-length CHAR and VARCHAR.
Not that it can be extremely useful but I can think of a situation when you truncate a column to 0 length when you no longer need it but you don't want to break existing code that writes something there. Anything you assign to a 0-length column will be truncated and a warning issued, but warnings are not errors, they don't break anything.
As they're similar types, char and varchar, I'm going to venture to guess that the use-case of varchar(0) is the same as char(0).
From the documentation of String Types:
MySQL permits you to create a column of type CHAR(0). This is useful
primarily when you have to be compliant with old applications that
depend on the existence of a column but that do not actually use its
value. CHAR(0) is also quite nice when you need a column that can take
only two values: A column that is defined as CHAR(0) NULL occupies
only one bit and can take only the values NULL and '' (the empty
string).
It's useful in combination with a unique index for if you want to mark one specific row in your table (for instance, because it serves as a default). The unique index ensures that all other rows have to be null, so you can always retrieve the row by that column.
You can use it to store boolean values.
Look this code:
mysql> create table chartest(a char(0));
Query OK, 0 rows affected (0.26 sec)
mysql> insert into chartest value(NULL);
Query OK, 1 row affected (0.01 sec)
mysql> insert into chartest value('');
Query OK, 1 row affected (0.00 sec)
mysql> select 'true' from chartest where a is null;
+------+
| true |
+------+
| true |
+------+
1 row in set (0.00 sec)
mysql> select 'false' from chartest where a is not null;
+-------+
| false |
+-------+
| false |
+-------+
1 row in set (0.00 sec)
We can use NULL to represent true and '' (empty string) to represent false!
According to MySQL reference manual, only NULL occupies one bit.
I have a service which produce formatted text files with information from certain tables in a MYSQL db.
Currently I programmatically query the DB and dump it in a TEXT file.
I wonder if i can do the same from within the MYSQL db.
This means that when a new record is added to a specific table, MYSQL will run a piece of code that will generate that formatted text file.
You didn't tell much about your use cases, but maybe the CSV engine might be what you're looking for?
From the manual:
When you create a CSV table, the server creates a table format file in the database directory. The file begins with the table name and has an .frm extension. The storage engine also creates a data file. Its name begins with the table name and has a .CSV extension. The data file is a plain text file. When you store data into the table, the storage engine saves it into the data file in comma-separated values format.
mysql> CREATE TABLE test (i INT NOT NULL, c CHAR(10) NOT NULL)
-> ENGINE = CSV;
Query OK, 0 rows affected (0.12 sec)
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
+------+------------+
| i | c |
+------+------------+
| 1 | record one |
| 2 | record two |
+------+------------+
2 rows in set (0.00 sec)
Starting with MySQL 5.1.9, creating a CSV table also creates a corresponding Metafile that stores the state of the table and the number of rows that exist in the table. The name of this file is the same as the name of the table with the extension CSM.
If you examine the test.CSV file in the database directory created by executing the preceding statements, its contents should look like this:
"1","record one"
"2","record two"
This format can be read, and even written, by spreadsheet applications such as Microsoft Excel or StarOffice Calc.
What are specific features from Postgres that are not available in MySQL?
Are there some queries that you wouldn't be able to do as easily? Or are the differences mostly in how you store your data?
I would say that two of the largest differences are WITH queries and window functions -- standard SQL features (from the SQL-99 standard) that are also available in other major SQL implementations (such as Oracle, DB2, SQL Server, ...), but not in MySQL.
Many minor things of course, e.g.:
MySQL has some non-standard conveniences, such as INSERT IGNORE and REPLACE, which PostgreSQL lacks. PostgreSQL's stored procedures and triggers can use any of several languages (such as Python, Java, Perl, ...), MySQL's (like DB2's) use the SQL'03 standard syntax here.
Also outside the standard, PostgreSQL has many peculiar data types (including user-defined types and multi-dimensional arrays), MySQL has unsigned integers.
What are specific features from Postgres that are not available in MySQL?
There are many, but most importantly: errors are raised when erroneous data is inserted --- and clients can't disable the sanity checks, as opposed to:
mysql> create table foo (id tinyint not null check id > 100);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into foo values (null), ('abc'), (128), ('1');
Query OK, 4 rows affected, 3 warnings (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 2
mysql> select * from foo;
+-----+
| id |
+-----+
| 0 |
| 0 |
| 127 |
| 1 |
+-----+
4 rows in set (0.00 sec)
Are there some queries that you wouldn't be able to do as easily?
Complex queries with lots of joins: PostgreSQL's query optimizer is vastly better, and nested loops isn't the only available join algorithm. Also, it can flatten sub-queries in the FROM-part of the query. Those are currently materialized in the stable releases of MySQL.