You can disable foreign key and run the script to check if mysql throws any errors other than foreign key constraint.
# cat foreign_key.txt
set foreign_key_checks=0;
# cat foreign_key.txt db_name_updates.sql | mysql db_name
_____
When you need to import data, it is better to disable foreign key checks temporarily so that queries do not fail.
mysql> SET foreign_key_checks = 0
The problem with this is that you have to insert the statement at the beginning of every import file. If mysql reconnects automatically, it "forgets" the setting. There is no way to disable it at server level.
mysql> SET GLOBAL init_connect='SET foreign_key_checks = 0';
We can use initial connect feature to disable foregin keys. Any user that does not have "super" privilege will follow this command.
If you are creating users with "grant all on *.* " syntax, then you are out of luck.
I would suggest that a new user can be created for the purpose of executing the scripts those needs to bypass the foreign key checks. The easiest way to create such user is given below:
grant all on *.* to 'reader'@'%' identified by 'reader@123' with grant option;
revoke super on *.* from 'reader'@'%';
You can now use the "reader" user to execute the scripts those needs to by executed at any cost and should bypass foreign-keys.
_____
In order to know the exact queries where mysql found an error, use the following syntax.
# cat db_name_updates.sql | mysql db_name -f -vvv > db_name_updates_success.txt 2> db_name_updates_err.txt
Labels: mysql tips
We are going to learn how update the production data to be in sync with the development server. We will use 3 utilities.
1) diff : This is linux built-in command to compare 2 files.
2) Maatkit: This will be used to compare checksum values of 2 tables and the data differences.
http://www.maatkit.org/doc/3) schemasync: This utility is used to compare structural differences.
http://schemasync.org/______________________________________
I) Schema sync
We will first make sure that the table structure of localhost mktest table matches with the SERVER_A table structure.
In the following example, the column "mytime" is missing. How do we know that? How do we create the alter table statement?
server:localhost
schema: test
mysql> select * from mktest;
+----+----------+--------+------+
| id | f_amount | myname | city |
+----+----------+--------+------+
| 1 | NULL | abc | NULL |
| 3 | NULL | abc | NULL |
| 6 | NULL | abc | NULL |
| 8 | NULL | abc | NULL |
| 9 | NULL | abc | NULL |
| 21 | NULL | abc | NULL |
+----+----------+--------+------+
6 rows in set (0.00 sec)
server: SERVER_A
schema: test
mysql> select * from mktest;
+----+----------+--------+------+--------+
| id | f_amount | myname | city | mytime |
+----+----------+--------+------+--------+
| 1 | NULL | abc | NULL | NULL |
| 3 | NULL | abc | NULL | NULL |
| 5 | NULL | abc | NULL | NULL |
| 6 | NULL | abc | NULL | NULL |
| 8 | NULL | abc | NULL | NULL |
| 9 | NULL | abc | NULL | NULL |
| 11 | NULL | abc | NULL | NULL |
+----+----------+--------+------+--------+
7 rows in set (0.00 sec)
# diff <(mysqldump -hSERVER_A -uroot -proot@123 test mktest --skip-extended-insert -d -R) <(mysqldump -hlocalhost -uroot -proot@123 test mktest --skip-extended-insert -d -R) --side-by-side --suppress-common-lines --width=190 | more
-- Host: SERVER_A Database: test | -- Host: localhost Database: test
`mytime` datetime default NULL, <
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1; | ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=latin1;
*** mytime column needs to be added and the table type needs to be changed from InnoDB to MyISAM ***
_____
The diff utility does not generate ready to execute alter statements. We need a third party utility called schemasync.
# schemasync mysql://root:root@123@localhost:3306/test mysql://root:root@123@SERVER_A:3306/test
# cat /home/shantanu/test.20110720.patch.sql
USE `test`;
ALTER TABLE `mktest` ADD COLUMN `mytime` datetime NULL AFTER `city`;
It will also generate an alter table statement to change the table type.
______________________________________
II) Data Sync:
Now that our structure is in order, let's see what records are added / updated.
server:localhost
schema: test
mysql> select * from mktest;
+----+----------+--------+------+--------+
| id | f_amount | myname | city | mytime |
+----+----------+--------+------+--------+
| 1 | NULL | abc | NULL | NULL |
| 3 | NULL | abc | NULL | NULL |
| 6 | NULL | abc | NULL | NULL |
| 8 | NULL | abc | NULL | NULL |
| 9 | NULL | abc | NULL | NULL |
| 21 | NULL | abc | NULL | NULL |
+----+----------+--------+------+--------+
6 rows in set (0.00 sec)
_____
server: SERVER_A
schema: test
mysql> select * from mktest;
+----+----------+--------+------+--------+
| id | f_amount | myname | city | mytime |
+----+----------+--------+------+--------+
| 1 | NULL | abc | NULL | NULL |
| 3 | NULL | abc | NULL | NULL |
| 5 | NULL | abc | NULL | NULL |
| 6 | NULL | abc | NULL | NULL |
| 8 | NULL | abc | NULL | NULL |
| 9 | NULL | abc | NULL | NULL |
| 11 | NULL | abc | NULL | NULL |
+----+----------+--------+------+--------+
7 rows in set (0.00 sec)
a) Checksum match:
We need to find out if the checksum values of these 2 tables match. If the row count and checksum values are the same, the table are exactly the same.
# /usr/bin/mk-table-checksum h=SERVER_A,u=root,p=root@123,P=3306 --databases test --tables mktest h=localhost,u=root,p=root@123,P=3306 --databases test --tables mktest --count | /usr/bin/mk-checksum-filter
test mktest 0 SERVER_A MyISAM 7 4d38da45 0 0 NULL NULL
test mktest 0 localhost MyISAM 6 f1e08b3d 0 0 NULL NULL
There is a difference of 1 row and the checksum value does not match. So we need to find out what are those records.
_____
b) Finding differences:
# diff <(mysqldump -hSERVER_A -uroot -proot@123 test mktest --skip-extended-insert) <(mysqldump -hlocalhost -uroot -proot@123 test mktest --skip-extended-insert) --side-by-side --suppress-common-lines --width=190 | more
-- Host: SERVER_A Database: test | -- Host: localhost Database: test
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1; | ) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=latin1;
INSERT INTO `mktest` VALUES (5,NULL,'abc',NULL,NULL); <
INSERT INTO `mktest` VALUES (11,NULL,'abc',NULL,NULL); | INSERT INTO `mktest` VALUES (21,NULL,'abc',NULL,NULL);
The above screen shows that one row is missing from localhost while the another row ID should be 11 instead of 21.
_____
c) Generate SQL:
So we need one insert statement and one update. The maatkit table sync utility has generated delete / insert combo instead of update as shown below:
# /usr/bin/mk-table-sync --print h=SERVER_A,u=root,p=root@123,P=3306 --databases test --tables mktest h=localhost,u=root,p=root@123,P=3306 --databases test --tables mktest
DELETE FROM `test`.`mktest` WHERE `id`='21' LIMIT 1 ;
INSERT INTO `test`.`mktest`(`id`, `f_amount`, `myname`, `city`, `mytime`) VALUES ('5', NULL, 'abc', NULL, NULL) ;
INSERT INTO `test`.`mktest`(`id`, `f_amount`, `myname`, `city`, `mytime`) VALUES ('11', NULL, 'abc', NULL, NULL) ;
Labels: mysql FAQ, mysql tips
Let's assume I want to remove all the older backup files from the current directory, except the last 2 latest files. One way of doing this is to move the latest file to another location and then remove all the files starting with data_diff_*
But such a process can not be set in cron nor it can be used in a script.
Here is a linux command that will do this for you. For free!!
# ls -lht
total 169M
-rw-r--r-- 1 root root 1.8M Apr 25 00:55 data_diff_0425.txt.zip
-rw-r--r-- 1 mysql mysql 1.8M Apr 24 00:55 data_diff_0424.txt.zip
-rw-r--r-- 1 mysql mysql 1.8M Apr 23 00:55 data_diff_0423.txt.zip
-rw-r--r-- 1 mysql mysql 1.8M Apr 22 00:55 data_diff_0422.txt.zip
-rw-r--r-- 1 mysql mysql 3.5M Apr 21 00:55 data_diff_0421.txt.zip
-rw-r--r-- 1 mysql mysql 1.8M Apr 20 00:55 data_diff_0420.txt.zip
...
# (ls data_diff_*.txt.zip -t | head -n 2; ls data_diff_*.txt.zip)| sort | uniq -u | xargs rm
# ls -lht
total 3.5M
-rw-r--r-- 1 root root 1.8M Apr 25 00:55 data_diff_0425.txt.zip
-rw-r--r-- 1 mysql mysql 1.8M Apr 24 00:55 data_diff_0424.txt.zip
Labels: linux tips, shell script