Skip to the content...

Welcome to the David Walsh Blog. I'm a MooTools, Dojo, jQuery, CSS, and PHP Web Developer located in Madison, Wisconsin, United States. Please contact me if I can make your experience on my website better.

Backup Your MySQL Database Using PHP

97 Responses »

One of the most important tasks any developer needs to do often is back up their MySQL database. In many cases, the database is what drives most of the site. While most web hosts do a daily backup of a customer's database, relying on them to make backups and provide them at no cost is risky to say the least. That's why I've created a database backup function that I can call whenever I want -- including nightly CRONs.

The PHP & MySQL Code

backup_tables('localhost','username','password','blog');


/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{
	
	$link = mysql_connect($host,$user,$pass);
	mysql_select_db($name,$link);
	
	//get all of the tables
	if($tables == '*')
	{
		$tables = array();
		$result = mysql_query('SHOW TABLES');
		while($row = mysql_fetch_row($result))
		{
			$tables[] = $row[0];
		}
	}
	else
	{
		$tables = is_array($tables) ? $tables : explode(',',$tables);
	}
	
	//cycle through
	foreach($tables as $table)
	{
		$result = mysql_query('SELECT * FROM '.$table);
		$num_fields = mysql_num_fields($result);
		
		$return.= 'DROP TABLE '.$table.';';
		$row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
		$return.= "\n\n".$row2[1].";\n\n";
		
		for ($i = 0; $i < $num_fields; $i++) 
		{
			while($row = mysql_fetch_row($result))
			{
				$return.= 'INSERT INTO '.$table.' VALUES(';
				for($j=0; $j<$num_fields; $j++) 
				{
					$row[$j] = addslashes($row[$j]);
					$row[$j] = ereg_replace("\n","\\n",$row[$j]);
					if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
					if ($j<($num_fields-1)) { $return.= ','; }
				}
				$return.= ");\n";
			}
		}
		$return.="\n\n\n";
	}
	
	//save file
	$handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
	fwrite($handle,$return);
	fclose($handle);
}

Of course, you'll need to provide database credentials to the function, as well as an array of tables you'd like to backup. If you provide a "*" or no tables, a complete database backup will run. The script does the rest!

Never take chances when your website is on the line. Make frequent backups or pay the price later!

Discussion

  1. August 18, 2008 @ 9:21 am

    This is something I’ve been meaning to do for a while now. Dreamhost does do regular backups they claim (have never had to use them), but I should really do this anyway.

  2. rich
    August 18, 2008 @ 11:11 am

    David, would you suggest doing this manually, or maybe setting up a cron to do this on a weekly basis. or maybe having mootools or jquery (hint hint)…to set up a timer to do this…that way it just overrides the last one and you always have a weekly backup of your Db at hand…just in case. any thoughts?

  3. August 18, 2008 @ 1:28 pm

    ok, noob checking in here. yes, i’m one of those “hmmm, what does that do…” sort of self-taught posters. most of the time i learn enough get into trouble. ;)

    anyway, from what i can ascertain from parsing your code, this should be a very sweet addition to the must-haves.

    but, as a noob, i’m not sure i grok where the file is being saved “to”

    i notice the save comment at the end, but cannot decipher where it’s actually saved.

    a little insight please?

    thanks! and thanks again for your blog.

  4. August 18, 2008 @ 4:58 pm

    @Rich: I wouldn’t trust jQuery or Moo to do this — this is definitely a server-side responsibility. Maybe a nightly or weekly CRON would be best. My blog emails me a DB backup weekely.

    @Michael: I’m writing a backup to a file called “db-backup-{current time}-{tables md5}.sql” file. That way it’s (theoretically) easy to tell when the backup was last run.

  5. rich
    August 18, 2008 @ 5:01 pm

    Kind of figured that. Awesome idea though. I usually do it manually very month. this will make life so much easier. Thanks again David!

  6. August 19, 2008 @ 2:53 am

    He David,
    What happend with the good old mysqldump command? Even gzipped for saving bandwith or diskspace.
    And in PHP code:

    <?php
    $output = `mysqldump –add-drop-table database-name | gzip > db.sql.gz`;
    ?>

    Or with pecific tables:

    <?php
    $output = `mysqldump –add-drop-table database-name table1,table2,table3 | gzip > db.sql.gz`;
    ?>

    Saves you a line or two ;)
    Cheers!

  7. martin
    August 19, 2008 @ 3:29 am

    That wont re-create all your indexes n stuff tho will it?

    mysqldump is the tool of choice.

  8. August 19, 2008 @ 4:30 am

    Nice article.

    Every webmaster should really set up a Cron like that to backup their database !!

    I made up a similar script for my websites.

    The solution of sending the sql by mail is not a good solution if your site become larger and larger. Or you need to save only recent entries and not all tables. If you have a ftp for storing the backup file, you could copy the file once a week on the ftp.

    Mysqldump is not accessible on all hosting services so this script is the solution.

  9. August 19, 2008 @ 5:04 am

    I know mysqldump is not available on every shared hosting. But I choose a more expensive hostng package or VPS when it is not available.
    This is IMHO not a security issue, so why should it not be available…

  10. August 19, 2008 @ 6:40 am

    @Martin, PrimeMinister: I chose this route because as the two posts after you mentioned, many hosting providers don’t allow the mysqldump functionality.

  11. gerry22
    August 19, 2008 @ 6:01 pm

    bug?

    for ($i = 0; $i < $num_fields; $i++) {
    $return.= ‘DROP TABLE ‘.$table.’;

    $row2 = mysql_fetch_row(mysql_query(‘SHOW CREATE TABLE ‘.$table));

    $return.= “\n\n”.$row2[1].”;\n\n”;

    loops through and creates multiple Drop Table and Create table mysql statements

    me thinks this part:

    $return.= ‘DROP TABLE ‘.$table.’;';

    $row2 = mysql_fetch_row(mysql_query(‘SHOW CREATE TABLE ‘.$table));
    $return.= “\n\n”.$row2[1].”;\n\n”;

    should be outside the “for” loop

  12. August 19, 2008 @ 9:59 pm

    I agree with you primeminister. A hosting provider should make mysqldump available some way or another.

  13. August 20, 2008 @ 1:53 am

    ereg() is slower than preg_match, and is being depreciated in php6.

    I would recommend exchanging the ereg() function with preg_match().

    Other than that, great script! (as usual)

  14. August 24, 2008 @ 12:31 am

    @ gerry22:

    Yup

    $return.= ‘DROP TABLE ‘.$table.’;';

    $row2 = mysql_fetch_row(mysql_query(‘SHOW CREATE TABLE ‘.$table));
    $return.= “\n\n”.$row2[1].”;\n\n”;

    Should be above:

    $result = mysql_query(‘SELECT * FROM ‘.$table);
    $num_fields = mysql_num_fields($result);
    for ($i = 0; $i < $num_fields; $i++)
    {

  15. August 25, 2008 @ 8:00 am

    @gerry22: Good call. I’ll fix the article as soon as I can.

  16. August 31, 2008 @ 4:01 pm

    am i the only person who groaned when I saw the DROP command being used.

    seriously, I havent looked closely through the code, but is it dropped a duplicated table or what is the DROP doing?!

  17. johnathan
    August 31, 2008 @ 8:54 pm

    It’s there in case you need to restore the table, must like PHPMyAdmin. What’s with the groand?

  18. September 2, 2008 @ 4:40 pm

    ok, sorry. I didnt read the code all the way through. Its writing it out rather than actually DROPPING the table in the backup processes. Thats what I get for commenting before I read the code…. :(

  19. elias
    September 7, 2008 @ 12:43 pm

    Hello David,

    I found this script very useful, but i have problems with blob data, the script wont get this data correctly.

    Thanks

  20. September 8, 2008 @ 9:15 pm

    Nice looking code, i have not tested it yet but i plan on doing so, im looking to modify the code a little to suit my needs (implement it into my members control panel) but il be sure to come back to you with the new work so you can repost it here :)

    yeah yeah im one of those hosts that doesnt permit sqldump lol, infact i dont use the main stream control panels for my hosting at all.

  21. October 1, 2008 @ 11:55 am

    Your post is a very good. I’ll download and try.

  22. October 10, 2008 @ 8:15 am

    One little modification I made:

    $return.= ‘DROP TABLE IF EXISTS ‘.$table.’;';

    Added the IF EXISTS !!

    Great script!!!, a live saver!!!

  23. bryce
    October 20, 2008 @ 12:35 am

    Now we just need a restoring script :)

  24. carl
    January 5, 2009 @ 1:31 pm

    Hi, I think what Michael was trying to say was…where is the actual file itself being saved to…is it the same directory as the the script, do I have to define it…or is there a pre-defined saving camp?

    Ta Much.

  25. January 5, 2009 @ 1:34 pm

    @Carl: The same directory as the script.

  26. michael
    January 5, 2009 @ 1:51 pm

    @Carl, & @David: thanks!

  27. carl
    January 5, 2009 @ 2:41 pm

    Gotcha, Thanks – I’m uploading now ;)

  28. john
    January 10, 2009 @ 10:43 am

    superb article, just what i had spent days looking for.

    As someone has previously posted though, how do we restore the database once it has ben backed up?

  29. kelvin
    January 15, 2009 @ 4:46 am

    A straight to the point script, just what i was looking for many thanks.

    One quick question, what is the purpose of (md5(implode(‘,’,$tables))) ? ?

  30. January 15, 2009 @ 8:47 am

    @Kelvin: It takes a string of the desired tables and md5′s them for the file name so that files aren’t constantly being overwritten.

  31. February 9, 2009 @ 7:47 am

    Would you mind sharing the script you use to email the file weekly?

  32. February 10, 2009 @ 5:34 pm

    If you’re getting an “Out of range value adjusted for column error” when trying to restore your backup, edit lines:

    if (isset($row[$j])) { $return.= ‘”‘.$row[$j].’”‘ ; } else { $return.= ‘”"‘; }

    with this:

    if (isset($row[$j])) {
    if ($row[$j] == null) {
    $return .= ‘null’ ;
    } else {
    $return .= ‘”‘.$row[$j].’”‘ ;
    }
    }
    else {
    $return .= ‘”"‘;
    }

  33. kunal
    February 16, 2009 @ 5:36 am

    what is the solution for ” how to transfer the file from one ftp server to the another ftp server directly plz explainning in details if possible for anyone”

  34. February 16, 2009 @ 10:17 pm

    nice, just what I was after, Thanks David

    @Micheal Fox – I’ve bolted on some script to send the sql, that I found here http://www.sitepoint.com/article/advanced-email-php/

    a little modified, only real difference is MIME type ‘application/x-sql’.

    just add the function below, and call it here in the original script `print(“fwrite($handle,$return);

    sendBackup($filename, $name);
    fclose($handle);”);`

    print(“<?php

    function sendBackup($newFileName, $name){
    // Read POST request params into global vars
    $to = ‘me@example.com;
    $from = ‘me@example.com;
    $subject = ‘Your Backup for ‘.$name;
    $message = ‘Backup for ‘.$name;
    // Obtain file upload vars
    $fileatt = $newFileName;
    $fileatt_type = “application/x-sql”;
    $fileatt_name = $newFileName;

    $headers = “From: $from”;

    // Read the file to be attached (‘rb’ = read binary)
    $file = fopen($fileatt,’rb’);
    $data = fread($file,filesize($fileatt));
    fclose($file);

    // Generate a boundary string
    $semi_rand = md5(time());
    $mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

    // Add the headers for a file attachment
    $headers .= “\nMIME-Version: 1.0\n” .
    “Content-Type: multipart/mixed;\n” .
    ” boundary=\”{$mime_boundary}\”";

    // Add a multipart boundary above the plain message
    $message = “This is a multi-part message in MIME format.\n\n” .
    “–{$mime_boundary}\n” .
    “Content-Type: text/plain; charset=\”iso-8859-1\”\n” .
    “Content-Transfer-Encoding: 7bit\n\n” .
    $message . “\n\n”;

    // Base64 encode the file data
    $data = chunk_split(base64_encode($data));

    // Add file attachment to the message
    $message .= “–{$mime_boundary}\n” .
    “Content-Type: {$fileatt_type};\n” .
    ” name=\”{$fileatt_name}\”\n” .
    //”Content-Disposition: attachment;\n” .
    //” filename=\”{$fileatt_name}\”\n” .
    “Content-Transfer-Encoding: base64\n\n” .
    $data . “\n\n” .
    “–{$mime_boundary}–\n”;

    // Send the message
    $ok = @mail($to, $subject, $message, $headers);
    if ($ok) {
    echo “Mail sent! “;
    } else {
    echo “Mail could not be sent. Sorry!”;
    }
    }
    ?>”);

  35. February 23, 2009 @ 11:12 am

    Add this code to the end to save on your local drive:

    $filename = ‘db-backup-’.time().’-’.(md5(implode(‘,’,$tables))).’.sql’;
    Header(“Content-type: application/octet-stream”);
    Header(“Content-Disposition: attachment; filename=$filename”);
    echo $return;

  36. February 27, 2009 @ 10:07 am

    Exporting in xml will create a huge file… am I wrong?

  37. February 27, 2009 @ 10:14 am

    Ahmad Alfy: It definitely would.

  38. subash
    March 5, 2009 @ 7:46 am

    i am very happy to find this code .it relay work fine and very few time to take a backup the database
    thanks

  39. March 8, 2009 @ 11:40 am

    Hi.

    As everyone, thanks for this simple script. I got it up and running in a matter of seconds.

    I plan on doing a daily backup. Is there a way you can automaticaly delete so that there is only 3 or 4 backups in the folder at a time – don’t want it to get to the point where I forget and there are hundres in there !!

  40. richei
    March 8, 2009 @ 1:11 pm

    This script saved my bacon! i had tried a few others but kept getting errors. Had a few errors on this one, but it was with me, not the script. Only thing i need to figure out is how to get it save to a specific folder, but i think i need to use the physical path instead of the relative one.

    Thanks for the script!

  41. March 9, 2009 @ 7:15 am

    It is a great script, but what about VIEWS ?
    The script recognize a VIEW as a TABLE and I get this:
    “DROP TABLE vw_customerorders;

    CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW vw_customerorders AS select unl_login.FirstName…….”

    “INSERT INTO vw_customerorders VALUES(“…………..”)
    For this issue what can be done ?

    Thank you for the script and the informations i usually get from your Blog.

  42. alvaro
    March 12, 2009 @ 10:31 am

    Great script!

    Just checked that NULL values are grabbed as “0″… perhaps It would be fixed as per below:

    if (isset($row[$j]) && ($row[$j] != NULL)) { $return.= ‘”‘.$row[$j].’”‘ ; } else { $return.= ‘NULL’; }

    Again… thank you for your script

  43. March 30, 2009 @ 3:01 pm

    I love yor filename pattern.. Thanks, scripts work and make me Understand :)

  44. dickram
    March 30, 2009 @ 8:50 pm

    Thank you very much. I was just googling about this stuff and found this. Not tested yet, but after reading the comments I know it will surely work!!
    Thanx and keep up the good work.

  45. June 1, 2009 @ 4:53 pm

    This is a really cool script you’ve got Dave, thanks! I’ll be pointing a link at you as soon as I can get it working on my client’s server. It’s working like a dream on my test site, but the DB on the client site is larger and the script keeps timing out 3 tables into the process (I have 16 total). If you have a work around, I’d love to hear it. Again, thanks for the jumpstart

  46. bob
    July 1, 2009 @ 8:33 am

    Thanks for sharing that. I’ll give it a try. It does look like a life saver.

    And do you have a similar script to run with a cron job to backup the web public directory in a .tar or .tgz file, prefix or suffix with the date?
    that would a great backup combo script !!!! and another interesting article.

    cheers and thanks

  47. July 9, 2009 @ 6:27 am

    Thanks, saved a load of time and taught a thing or two.

    For those worried about having too many backup files stored, add a simple table on your database to store the details of your backups and use this info to purge unwanted files – for example – run the below from your sql window to create the table.

    CREATE TABLE `backup` (
    `id` tinyint(10) NOT NULL auto_increment,
    `name` varchar(50) NOT NULL,
    UNIQUE KEY `id` (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    Where David recommends saving using the code:

    //save file
    $handle = fopen(‘db-backup-’.time().’-’.(md5(implode(‘,’,$tables))).’.sql’,'w+’);
    fwrite($handle,$return);
    fclose($handle);

    If you instead use

    $now=time();
    //save file – this is using a different format to the one above to help keep the filename samaller in size (personal preference)
    $handle = fopen(‘db-backup-’.$now.’.sql’,'w+’);
    fwrite($handle,$return);
    fclose($handle);

    $sql=”INSERT INTO backup (name)
    VALUES
    (‘db-backup-”.$now.”.sql’)”;if (!mysql_query($sql))
    //file saved to the database you created above
    {
    die(‘Error: ‘ . mysql_error());
    }
    //change the LIMIT 14 to be the number of backups you want to keep. For example I run this once a day so saving the 14 latest backups provides a 2 week window.
    $query=”SELECT * FROM backup ORDER BY id DESC LIMIT 14,100″;
    $result = mysql_query($query);
    while($row = mysql_fetch_array($result, MYSQL_ASSOC)){
    //removes unwanted backup files and then removes their details from the database
    $name=$row['name'];
    unlink ($name);
    $sql=”DELETE FROM backup WHERE name=’$name’”;
    if (!mysql_query($sql))
    {
    die(‘Error: ‘ . mysql_error());
    }

    };

    And using this will allow you to only keep a limited amount of backups, with the oldest being deleted as a new one is created. I hope this helps keep your backup-footprint down :)

    Great White

  48. July 18, 2009 @ 1:51 pm

    Thanks for this script! Worked like a charm.

    I would like to ask a question. Could you show us on how to then make something which the user can click on the button to download the file create?

    Thanks a lot. Please contact me here or on my email. Thanks.

  49. tenzin
    July 31, 2009 @ 2:08 pm

    Nice work,
    I tried it instantly and it did back up my DB. But I saw problem with a character encoding. It lost all the character informations, all I can see is lots and lots of ?????????????? marks :-(. I tried with phpmyadmin dump, it don’t show this problem. My sites language is Tibetan and German ( with german chars. no problems ). Any idea or suggestion for fix.
    Thanks a lot
    Tenzin

  50. giedrius
    August 9, 2009 @ 2:50 pm

    Not so bad. But I tried to save all db tables with *.
    And theses tables without records, were dropped and after that not created.
    bug?

  51. August 9, 2009 @ 4:08 pm

    I tried a script that ran mysqldump through the PHP system() and it did nothing but create a blank file. This one works like a bloody charm and is better than relying on using a system command, which can vary if moved to a different server. Though I chopped all the login stuff out since each page is always logged into the database that needs backing up
    THANKS!

  52. philip
    August 10, 2009 @ 4:37 pm

    It doesn’t seem to be exhaustiv but Thanks!

  53. lorand
    August 13, 2009 @ 4:04 am

    What is the goal of the first loop on line 36?

    for ($i = 0; $i < $num_fields; $i++)

    On line 41 you have again the same loop:

    for($j=0; $j<$num_fields; $j++)

    Is it necessary to loop two time through the table fields? May be there is something I don’t understand. Thank you.

  54. dave
    August 16, 2009 @ 9:16 pm

    I have been using this script and hit a glitch when I tried restoring a hacked Joomla site tonight. I noticed some of my articles were getting cut off occasionally when a single or double quote was used in the article. I looked at the backup created by this script and noticed some of the quotes in the SQL backup didn’t get escaped with a “\”, so now I have to manually go through the backup and add them where they were missed so the restore goes through properly. Has anyone run into this problem? I really love this script but now I’m worried about running into a similar issue on a more robust site which would be a nightmare to manually go through and add slashes that were skipped!

  55. August 23, 2009 @ 9:56 am

    Hi I am facing this error please help me

    Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 128921702 bytes) in /home/webmaste/public_html/dewshare.com/forums/backup.php on line 46

  56. dan
    August 27, 2009 @ 4:01 am

    first of all thanks david for these awsome tutorials,you helped a lot in understanding mootools ;).

    Right now i’m doing kind of a toolbox where i collect all kinds of useful classes or write them myself,in the last days i did a login with php/mysqli, because i wanted to use the mysqli-prepared-statement functionality.
    as i browsed through your tuts today i found the ‘create-a-zip’ and this tut,so i went on and combined these with my mysqli_wrapper_class ( i had to rewrite your backup-script as well :> ).
    Right now i’m searching for a way to make an backup-file for every table in the selected database,just a little more fixing.

    greetz from germany (yeah,we can code too)

  57. oluwaseun
    September 9, 2009 @ 7:13 pm

    i must commend your effort in displaying thsi code.this i have been looking for for my many weeks now.God bless you.thanks so much.

  58. October 6, 2009 @ 10:06 am

    Actualy there’s a little mistake in line 41. Where it says:


    for($j=0; $j<$num_fields; $j++)

    It should say

    $columns = count($row);
    for($j=0; $j<$columns; $j++)

    I hope this helps everybody and specially @Lorand.

    For those how use mysqli here’s my modified version:

    foreach($tables as $table){
    /* Drop previous tables */
    $return.= 'DROP TABLE IF EXISTS '.$table.';';

    /* Get 'how to' create the table */
    $result = $this->link->query('SHOW CREATE TABLE '.$table);
    $row = $result->fetch_array(MYSQL_NUM);
    $return.= "\n\n".$row[1].";\n\n";

    $result = $this->link->query('SELECT * FROM '.$table);
    $num_fields = $result->num_rows;

    for ($i = 0; $i fetch_array(MYSQL_NUM)) {
    $columns = count($row);
    $return.= 'INSERT INTO '.$table.' VALUES(';
    for($j=0; $j<$columns; $j++) {
    $row[$j] = addslashes($row[$j]);
    $row[$j] = preg_replace("/\n/","\\n",$row[$j]);
    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
    if ($j<($num_fields-1)) { $return.= ','; }
    }
    $return.= ");\n";
    }
    }
    $return.="\n\n\n";
    }

  59. chidi
    October 9, 2009 @ 7:22 am

    Wow!! it worked like magic. Could you please give a tutorial for exporting tables in a database to excel? will be glad if you would.

    thanks

  60. November 16, 2009 @ 6:51 am

    Add these lines at the line 4 and it will can backup UTF-8 databases:

    mysql_query(‘SET NAMES utf8′);
    mysql_query(‘SET CHARACTER SET utf8′);

    Byez!

  61. charan
    November 20, 2009 @ 7:41 am

    great script… will try it out

  62. mrtutu
    November 27, 2009 @ 10:54 am

    Thank you ! It works perfect and i spare time…

  63. December 9, 2009 @ 4:28 am

    thanks, myself and a mate just used this script. very handy. you’ve saved us a lot of effort :)

  64. December 16, 2009 @ 9:34 am

    David,
    Nice script! I added a little something I’d like to share. When naming the file, I put the date and table as the name.

    //save file
    if ($tables = ‘*’) {
    $table=”all”;
    }
    // if your not backing up all(*) the tables, it appends that table name to the end of the file.

    $handle = fopen(‘db-backup-’. date(“Ymd”) .’-’. $name .’-’. $table. ‘ .sql’,'w+’);

    Gives you something like: db-backup-20091216-mydatabase-all.sql

    Hope that helps someone, thanks again David

  65. razvan
    January 3, 2010 @ 2:29 am

    beautiful.. thanks

  66. juanantonio
    January 4, 2010 @ 4:44 pm

    great script.. can some one give me a script for restoring the DB, i tried a script but only reads the first 3000 lines, my DB its big (141200 lines) ..please i need some help

    thanks

  67. January 8, 2010 @ 7:12 am

    Amazing!
    My former (free) host had connections issues for phpMyAdmin, so I wasn’t able to export my database. Thanks to you now I saved it!

    Thank you for this amazing script.

  68. January 8, 2010 @ 7:23 am

    Aw I just forgot to add that you should modify a line in the script :
    $return.= ‘DROP TABLE ‘.$table.’;';

    should be :
    $return.= ‘DROP TABLE IF EXISTS ‘.$table.’;';
    in order to avoid any “inexistant talbe” warnings.

    Cheers,

  69. vasu
    January 18, 2010 @ 1:47 am

    The script is not fetching value…. in insert query.

  70. January 24, 2010 @ 8:33 am

    First off nice script give me a starting point for a good backup system.
    There should be a
    $return = ” ;
    just after
    mysql_select_db($name,$link);
    this way you dont get a notice of undefind return
    I also did a little mod to you system and added to My $db class
    and added a choice of rather to do just the structure or just the data
    function backup_tables($host=”,$user=”,$pass=”,$name=”,$tables = ‘*’,$struc=false,$data=false)
    {
    global $db;
    $return = ”;

    //get all of the tables
    if($tables == ‘*’)
    {
    $tables = array();
    $result = $db->sql_query(‘SHOW TABLES’);
    while($row = $db->sql_fetchrow($result))
    {
    $tables[] = $row[0];
    }
    }
    else
    {
    $tables = is_array($tables) ? $tables : explode(‘,’,$tables);
    }

    //cycle through
    foreach($tables as $table)
    {
    $result = $db->sql_query(‘SELECT * FROM ‘.$table);
    $num_fields = $db->sql_numfields($result);

    if($struc)$return.= ‘DROP TABLE ‘.$table.’;';
    $row2 = $db->sql_fetchrow($db->sql_query(‘SHOW CREATE TABLE ‘.$table));
    if($struc)$return.= “\n\n”.$row2[1].”;\n\n”;

    if($data){
    for ($i = 0; $i sql_fetchrow($result))
    {
    $return.= ‘INSERT INTO ‘.$table.’ VALUES(‘;
    for($j=0; $j<$num_fields; $j++)
    {
    $row[$j] = addslashes($row[$j]);
    $row[$j] = ereg_replace("\n","\\n",$row[$j]);
    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
    if ($j<($num_fields-1)) { $return.= ','; }
    }
    $return.= ");\n";
    }
    }
    }
    $return.="\n\n\n";
    }

    //save file
    $handle = fopen('./backups/db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
    }
    backup_tables($host,$user,$pass,$db,$tables = '*',false,true);
    returns only data
    backup_tables($host,$user,$pass,$db,$tables = '*',true,false);
    returns only structure
    backup_tables($host,$user,$pass,$db,$tables = '*',true,true);
    returns all

  71. jamus
    January 28, 2010 @ 4:48 am

    Great script! I have to add the tables for it to run though. Leaving ‘*’ results in the ‘mysql_num_fields(): supplied argument is not a valid MySQL’ error. Is this because of my host?

  72. jamus
    January 28, 2010 @ 5:17 am

    Also, I’ve just compared a out from this script to one from phpmyadmin.

    Text content that had a line break included is being output incorrectly and actually creating a line break in the .sql.

    ” Cras pulvinar\r\ndui in urna sagittis”

    ” Cras pulvinar
    \ndui in urna sagittis”

    Any ideas why this might be?

  73. arnold
    February 20, 2010 @ 10:03 am

    guys i have problem with utf-8 , i dont know where to add

    mysql_query(‘SET NAMES utf8′);
    mysql_query(‘SET CHARACTER SET utf8′);

    someone says in line 4 but i test that and still my records are in ? marks

    plz tell exact place of code

  74. February 20, 2010 @ 10:37 am

    Your text editor is UFT-8 compilant?

  75. arnold
    February 20, 2010 @ 12:50 pm

    thanx guys problem was in importing db file in SSH

    but still i can not compress the sql file

    i wonder how i can create gz file to save bandwidth

  76. February 20, 2010 @ 3:34 pm

    Simple as:
    gzip yourfile.sql

  77. February 24, 2010 @ 5:20 am

    What would be the solution to let’s say delete 3 days old backups, as they are in this form:

    hostname.com-db-backup-’.date(‘Y-m-d–H-i’).zip

  78. February 24, 2010 @ 9:18 pm

    @Lorand: I don’t understand it either. The $i loop seems useless to me, rows are only fetched on the first iteration, the rest do nothing . Am I missing something?

    But thanks for the script btw. :)

  79. aleksandar
    March 2, 2010 @ 9:43 am

    Another useful thing in the script would be to add:
    $return = “SET FOREIGN_KEY_CHECKS=0;\n\n”;
    on line 25, and
    $return .= “SET FOREIGN_KEY_CHECKS=1;\n”;
    on line 53.

    So the script manages to update the database, without causing the #1217 – “Cannot delete or update a parent row: a foreign key constraint fails” error.

    Regards,
    Aleksandar

  80. March 6, 2010 @ 3:02 pm

    Excellent article!

    I must say this was a lot easier than I thought that it would be.

    I am curious, how would I prompt the user to save the file locally?

    Keep on truckin’!

    64Pacific

  81. March 13, 2010 @ 2:54 pm

    Thanks Davids…
    It really help me to create a daily backup on my dbase server…

  82. zoran
    April 29, 2010 @ 1:19 pm

    This is very useful, thanks for the time you took to create this function.

  83. dejan
    May 10, 2010 @ 9:01 pm

    Great piece of code, although the UTF-8 characters stored in db are converted into question marks.
    Anyone with a solution on this?

  84. zoran
    May 11, 2010 @ 3:11 am

    @Dejan
    Try and store your text fields with utf_general_ci encoding when creating tables, it works for me for Macedonian characters.

  85. May 18, 2010 @ 9:44 am

    Thanks for the script…. It saved my time….

  86. ilshat
    May 20, 2010 @ 11:59 am

    Thank you Dave, you’ve saved my fat a*se!

  87. June 11, 2010 @ 4:01 am

    Very helpful to add database backup functionality..
    I got restore functionality
    http://dan.cx/blog/2006/12/restore-mysql-dump-using-php/

  88. alvaro
    June 17, 2010 @ 10:08 am

    Hi,

    What about innodb tables? How do you back them up?

    Thanks

  89. yavor marinov
    June 18, 2010 @ 5:47 pm

    Hi, great work!

    I have a table named: ‘pears-1_00-1_49′.
    The script bugs because of the special characters in name of the table.
    So I fixed it by using sprintf() for the query on three places:

    sprintf(“SELECT * FROM `%s`;”, $table);

    sprintf(“SHOW CREATE TABLE `%s`”, $table);

    sprintf(“INSERT INTO `%s` VALUES(“, $table);

    It works for me!

    Thanks to all!

  90. sheetal
    June 25, 2010 @ 3:04 am

    Hello David ,

    Nice script.I tested it.
    Now it is creating sql files backend in that folder.We have to go to that folder to check that it is there or not.
    I want option to download that sql file on click of button.How to do that?

    One more thing I don’t understand how u use $return.= “\n\n”.$row2[1].”;\n\n”; to get attributes of field.Can u explain me it little bit?

    Thanks & Regards,
    Sheetal

  91. erick alcala
    June 29, 2010 @ 6:23 pm

    Hey David,

    great info you are providing. I am trying to do a php component for joomla with your code, but I need to specify a suffix on the name for it to only backup the ones that have that suffix.

    I want to backup tables that start with
    jos_vm

    Do you have any idea how can I do this?. or anyone? =).. thanks

  92. tejas sali
    June 30, 2010 @ 6:45 am

    The script runs without any problems locally. But when I try to do the same on the web server, I get warnings on

    16 while($row = mysql_fetch_row($result))

    30 $num_fields = mysql_num_fields($result)

    38 while($row = mysql_fetch_row($result)

    Warning: mysql_num_fields(): supplied argument is not a valid MySQL result resource

    Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource

    And the back up file is created with just the ‘drop statement’ sometimes or an empty file is returned.

    Any clue?

  93. shafi ahamed
    July 2, 2010 @ 6:34 am

    Hey,

    Thanks man.your code working perfectly

    Regards,
    Shafi.SD

  94. July 2, 2010 @ 12:25 pm

    very useful stuff, thanks for sharing!

  95. July 23, 2010 @ 2:16 am

    Hi David,

    You did well, Its working fine but the sql file have
    DROP TABLE ‘table name’
    if I was drop the table after import your extract database files its throw error
    I was correction that as follows

    DROP TABLE IF EXISTS ‘table name’
    otherwise excellent

    Thank You
    Thulasidharan.PT

  96. sudeep
    August 6, 2010 @ 7:58 am

    @primeminister: i tried the code (mysqldump) but nothing happened, can u suggest anything?

  97. August 13, 2010 @ 11:41 pm

    Hey!

    I am a website developer and I make MLM websites which has so much importance of database.

    This is very useful code. Yesterday my client’s website database corrupted somehow and I wasn’t having backup. So If I would have applied this code and given him the module to backup the database himself then I would not be in mess in which I am right now.I had talked to the server support and they have told me to gave me backup file but it will also take time so it is bit unwanted situation.I am in it though I haven’t done anything wrong but one thing is I also haven’t done the right thing.

    So from now on I’ll give this functionality to backup to all my new clients and also the existing ones.

    I have also modified the code which will give you file to save when you run it. This may be useful to others who has been in situation that I am right now.

    backup_tables(‘hostname’,'username’,'password’,'database_name’);

    /* backup the db OR just a table */
    function backup_tables($host,$user,$pass,$name,$tables = ‘*’)
    {
    global $file;

    $link = mysql_connect($host,$user,$pass);
    mysql_select_db($name,$link);

    //get all of the tables
    if($tables == ‘*’)
    {
    $tables = array();
    $result = mysql_query(‘SHOW TABLES’);
    while($row = mysql_fetch_row($result))
    {
    $tables[] = $row[0];
    }
    }
    else
    {
    $tables = is_array($tables) ? $tables : explode(‘,’,$tables);
    }

    //cycle through
    foreach($tables as $table)
    {
    $result = mysql_query(‘SELECT * FROM ‘.$table);
    $num_fields = mysql_num_fields($result);

    $return.= ‘DROP TABLE if exists ‘.$table.’;';
    $row2 = mysql_fetch_row(mysql_query(‘SHOW CREATE TABLE ‘.$table));
    $return.= “\n\n”.$row2[1].”;\n\n”;

    for ($i = 0; $i < $num_fields; $i++)
    {
    while($row = mysql_fetch_row($result))
    {
    $return.= 'INSERT INTO '.$table.' VALUES(';
    for($j=0; $j<$num_fields; $j++)
    {
    $row[$j] = addslashes($row[$j]);
    $row[$j] = ereg_replace("\n","\\n",$row[$j]);
    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
    if ($j

    window.close();

Be Heard!

Share your thoughts with fellow developers of all skill levels! I want to hear from you!

Name*:
Email*:
Website:  
Wrap your code with <code> tags, f00!