I have set up a system whose purpose it is to generate incremental dumps of our production data to our data warehouse. "Incremental" in this sense means that we can "synchronize" the production database with our data warehouse every minute or so without having to generate a full dump. Instead, we are just dumping and inserting the new/changed data.
On our replication save, I have set up a system where every relevant table of our production database has one insert TRIGGER and one update TRIGGER. These copy every row which is inserted or updated into an "audit table" in a different schema. This audit schema contains tables with the same structure as the production tables, but no indexes, and by using those TRIGGERs the audit tables will only contain the new or updated rows since the last export.
At the moment I'm using the mysql command line client to do the following for each of these audit tables:
LOCK TABLES table WRITE
SELECT * FROM table
DELETE FROM table
UNLOCK TABLES
I then pipe the output to some other scripts for further processing.
Now this works perfectly fine, however it creates the problem that while the state of every individual table will be consistent, the entire set of tables won't be. For example, if I have a clicks table and an impressions table and there is a 1 minute delay between dumping the former and the latter, the entire dump will be in a state which is inconsistent, obviously.
Now my question is: How do I do the following:
Lock ALL tables
Generate dumps for ALL tables
Delete all data from ALL tables
Unlock tables
I cannot use the mysql command line client because I cannot keep the lock across different sessions, and each table requires a new command. Also, I checked mysqldump which allows dumping multiple tables at a time, but I didn't find a way to delete all data from the tables before releasing the locks.
Any ideas?
To perform the first two points the command could be this one :
mysqldump --lock-all-tables -u root -p DATABASENAME > nameofdumpfile.sql
Since it is not possible to perform step 3 and 4 without releasing the lock, at least with mysqldump utility, why don't copy all the tables into another database (backup db) and then export the dump file from it ?
CREATE DATABASE backupdb;
USE originaldb;
FLUSH TABLES WITH READ LOCK;
keep this prompt(Prompt 1) open and then clone the database from another command prompt(Prompt 2) :
mysqldump --lock-all-tables -u root -p originaldb | mysql -u backup -p password backupdb;
Drop the original database from the Prompt 1 :
USE backupdb;
DROP DATABASE originaldb;
Then restore the empty database back with its original name (note the -d flag ) :
mysqldump --lock-all-tables -u root -p backupdb | mysql -u backup -p password originaldb;
This could be an example of a workaround that you can apply to achieve what you need.
Related
I'm working with a mySQL database located on a separate cluster. Since the changes were few, I was just dumping the whole db and porting it to a fresh database each time. But now changes on the main db are more frequent, so I am looking for something that allows me to just "update" the tables of my existing db after having dumped it from the main site.
I am dumping the db using
mysqldump --master-data -h my_main_server -u my_dump_user -pmy_password mydb > dbdump.sql
How can I use it to "update" my current db?
Since you'd have the tables created already, the dump would fail whilst trying to create them, so for you to be able to execute the dump, you need to drop all the existing tables in the database.
You could have instructions in your dump to do that, so you could execute that command without a problem, or you can just reset the database.
If you really need to update some parts of the db with that dump, you could just comment out all the ALTER and CREATE TABLE instructions and just keep the INSERTS, if that's what you want.
I'm migrating a MYSQL DB from one host to another so I run the following command to backup the DB from the old hosting:
mysqldump -u **** -p **** | gzip > /home/***/***.sql.gz
And then use the following command to import the DB to the new host:
zcat /home/***/***.sql.gz | mysql -u *** -p ***
After successfully importing the DB, I point the domain to the new DNS.
The problem is that the website is active so new records are very likely to get inserted after the last backup. So, I may need to run the command once again after full DNS propagation.
So, my question, does the mysql command insert the new rows and update the existing ones or does it actually totally drop the tables and start over with the backup? If that happens, the records that have been inserted after DNS propagation might get lost!
Thanks
If you look at the output of mysqldump (before you gzip it) you will see that it contains a sequence of
DROP TABLE x;
CREATE TABLE x (...);
INSERT INTO x (...) VALUES (...);
So, no, it does not do an insert / replace, it drops and recreates the tables.
We have some tables that have huge number of records and which are not used often(e.g. user_activities) and we want to have ability to archive(I mean move) records from target table into archive table in separate database.
My question is: are there known solutions for that?
Additional explanation:
I'd like to have some kind of a rake task that would trigger archiving process. The process would go through tables marked as 'archived' (or whatever) and move outdated records to archive table in separate database.
Example: user_activities has 30 000 records. I mark the table as archived and set cutoff by id - last 2000 records. I expect the following results:
user_activities contains latest 2000 records only
28 000 outdated records have been moved to archived_user_activities table in my_super_cool_named_database
PS we use mysql2 adapter (if it helps)
Thank you!
There is the dump command and restore command I have shown below that work with the entire database.
copy the database:
mysqldump -u [uname] -p[pass] [dbname] > [backupfile.sql]
Use this method to rebuild a database from scratch:
$ mysql -u [username] -p [password] [database_to_restore] < [backupfile]
Use this method to import into an existing database (i.e. to restore a database that already exists):
$ mysqlimport [options] database textfile1
To restore your previously created custback.sql dump back to your 'Customers' MySQL database, you'd use:
$ mysqlimport -u sadmin -p pass21 Customers custback.sql
Although if you only want a specific part of the db you can do something like this...
CREATE TABLE db2.table LIKE db1.table;
INSERT INTO db2.table SELECT * FROM db1.table;
Situation: our production mysql database makes a daily dump into a .sql file. I'd like to keep a shadow database that is relatively up to date.
I know that to create a mysql database from a .sql file, one uses:
mysql -u USERNAME -p DATABASENAME < FILE.SQL
For our db, this took 4-5 hours. Needless to say, I'd like to cut that down, and I'm wondering if there's a way to just update the db with what's new/changed. On Day 2, is there a way to just update my shadow database with the new .sql file dumped from the production db?
MySQL Replication is the way to go.
But, in cases, where that is not possible, use the following procedure:
Have a modifed timestamp column in all your tables and update this value whenever a row is inserted/changed.
Use the following mysqldump options to take the incremental SQL file (this uses REPLACE commands instead of insertcommands, since the existing record will be updated in the backup database).
Keep a timestamp value somewhere placed in the file system. and use it in the where condition. MDFD_DATE is the column name on which you need to filter. On successful backup, update the value stored in the file.
skip-tz-utc prevents MSQL from automatically adjusting the timestamp values, based on your timezone.
mysqldump --databases db1,db2 --user=user --password=password --no-create-info --no-tablespaces --replace --skip-tz-utc --lock-tables --add-locks --compact --where=MDFD_DATE>='2012-06-13 23:09:42' --log-error=dump_error.txt --result-file=result.sql
Use the new sql file and run it in your server.
Limitations:
This method will not work if some records are deleted in your database. You need to manually delete them from the backup databases. Otherwise, keep a DEL_FLAG column and update it to 'Y' in production for deleted records and use this condition to delete records in the backup databases.
This problem can be solved using mysql synchronization.
Some links to guide you:
http://www.howtoforge.com/mysql_database_replication
Free MySQL synchronization tool
https://launchpad.net/mysql-proxy
https://www.google.com.br/search?q=mysql+synchronization
I have a mysql dump created with mysqldump that holds all the tables in my database and all their data. However I only want to restore two tables. (lets call them kittens and kittens_votes)
How would I restore those two tables without restoring the entire database?
Well, you have three main options.
You can manually find the SQL statements in the file relating to the backed up tables and copy them manually. This has the advantage of being simple, but for large backups it's impractical.
Restore the database to a temporary database. Basically, create a new db, restore it to that db, and then copy the data from there to the old one. This will work well only if you're doing single database backups (If there's no CREATE DATABASE command(s) in the backup file).
Restore the database to a new database server, and copy from there. This works well if you take full server backups as opposed to single database backups.
Which one you choose will depend upon the exact situation (including how much data you have)...
You can parse out CREATE TABLE kittens|kitten_votes AND INSERT INTO ... using regexp, for example, and only execute these statements. As far as I know, there's no other way to "partially restore" from dump.
Open the .sql file and copy the insert statements for the tables you want.
create a new user with access to only those 2 tables. Now restore the DB with -f (force) option that will ignore the failed statements and execute only those statements it has permission to.
What you want is a "Single Table Restore"
http://hashmysql.org/wiki/Single_table_restore
A few options are outlined above ... However the one which worked for me was:
Create a new DB
$ mysql -u root -p CREATE DATABASE temp_db
Insert the .sql file ( the one with the desired table ) into the new DB
$ mysql -u root -p temp_db < ~/full/path/to/your_database_file.sql
dump the desired table
$ mysqldump -u root -p temp_db awesome_single_table > ~/awesome_single_table.sql
import desired table
$ mysql -u root -p original_database < ~/awesome_single_table.sql
Then delete the temp_db and you're all golden!