Este artículo muestra cómo realizar un backup parcial o completo de bases de datos MySQL utilizando tan sólo código PHP. Esto es muy útil por ejemplo cuando un cliente no nos facilita datos de acceso a la base de datos de una aplicación web y sólo disponemos de un acceso FTP, o cuando sí disponemos de los datos de conexión a la base de datos pero no podemos acceder a ella a través de la red (sólo disponible en localhost) y tampoco podemos utilizar herramientas como mysqldump para respaldar la información porque no disponemos de privilegios para ello, o simplemente porque no tenemos acceso a una shell a la que conectarnos y ejecutar comandos.
ACTUALIZACIÓN 28/08/2017: trasladado el código fuente de los scripts myphp-backup.php y myphp-restore.php a mi repositorio de GitHub daniloaz/myphp-backup: https://github.com/daniloaz/myphp-backup
Backup de las tablas de una base de datos MySQL
En cualquiera de los escenarios anteriores, simplemente copiando y ejecutando el script PHP myphp-backup.php como indico más abajo podremos hacer un export completo o parcial (sólo algunas tablas) de la base de datos a un fichero .sql o .sql.gz que podremos descargar después desde la misma cuenta FTP. El script incluye la clase Backup_Database que se encarga de realizar todas las operaciones necesarias y dispone de distintas opciones de configuración para controlar en qué subdirectorio queremos que se almacenen los ficheros de backup y si queremos que se compriman con gzip o no. También deberemos establecer las credenciales de usuario para acceder a la base de datos, así como el nombre de ésta:
/** * Define database parameters here */ define("DB_USER", 'your_username'); define("DB_PASSWORD", 'your_password'); define("DB_NAME", 'your_db_name'); define("DB_HOST", 'localhost'); define("BACKUP_DIR", 'myphp-backup-files'); // Comment this line to use same script's directory ('.') define("TABLES", '*'); // Full backup //define("TABLES", 'table1 table2 table3'); // Partial backup define("CHARSET", 'utf8'); define("GZIP_BACKUP_FILE", true); // Set to false if you want plain SQL backup files (not gzipped)
Normalmente las aplicaciones PHP disponen de un fichero de configuración tipo config.php o similar en el que podremos encontrar el usuario y contraseña de la base de datos en caso de no recordarlas o si nuestro cliente no nos ha facilitado dicha información.
Si no disponemos de permisos suficientes para crear el subdirectorio donde se almacenarán nuestros ficheros de copia de seguridad (por defecto myphp-backup-files/), podremos utilizar un directorio existente. Normalmente las aplicaciones PHP disponen de algún subdirectorio con suficientes permisos para crear nuevos archivos (cache, tmp, temp, etc.), que es donde diremos a nuestro script myphp-backup.php que deje el fichero con el backup de la base de datos. También podremos usar el propio directorio raíz (DocumentRoot). Para ello asignaremos simplemente un punto (‘.’) a la constante BACKUP_DIR.
El fichero .sql.gz o .sql generado como resultado de utilizar la clase Backup_Database del script myphp-backup.php tendrá un nombre del tipo myphp-backup-{DB_NAME}-YYYYmmdd_HHMMSS.sql.gz:
$ ls myphp-backup-files/*.sql.gz myphp-backup-files/myphp-backup-smf-20160131_111735.sql.gz
Restauración de las tablas de una base de datos MySQL
El fichero anterior contendrá el código SQL comprimido (o no) listo para reproducir la estructura y el contenido de la base de datos original en otra base de datos distinta o en la misma sustituyendo los datos existentes por los de nuestro fichero de backup. Para efectuar la restauración simplemente ejecutaremos el otro script de mi repositorio: myphp-restore.php. Lo único que tendremos que hacer para realizar la restauración es subir al servidor en el que queramos hacer la importación tanto el script myphp-restore.php como el propio fichero de backup, que indicaremos mediante la constante BACKUP_FILE a una carpeta en la que tengamos permisos de escritura y que indicaremos mediante la constante BACKUP_DIR.
Las opciones de configuración de las que dispone el script myphp-restore.php son las siguientes:
/** * Define database parameters here */ define("DB_USER", 'your_username'); define("DB_PASSWORD", 'your_password'); define("DB_NAME", 'your_db_name'); define("DB_HOST", 'localhost'); define("BACKUP_DIR", 'myphp-backup-files'); // Comment this line to use same script's directory ('.') define("BACKUP_FILE", 'your-backup-file.sql.gz'); // Script will autodetect if backup file is gzipped or not based on .gz extension define("CHARSET", 'utf8');
El script detectará automáticamente si el fichero de copia de seguridad está comprimido o no con gzip basándose en la extensión de éste, por lo que no tendremos que establecer ninguna configuración adicional para esto.
Error: Your Requested widget " ai_widget-6" is not in the widget list.
- [do_widget_area above-nav-left]
- [do_widget_area above-nav-right]
- [do_widget_area footer-1]
- [do_widget id="wpp-4"]
- [do_widget_area footer-2]
- [do_widget id="recent-posts-4"]
- [do_widget_area footer-3]
- [do_widget id="recent-comments-3"]
- [do_widget_area footer-4]
- [do_widget id="archives-4"]
- [do_widget_area logo-bar]
- [do_widget id="oxywidgetwpml-3"]
- [do_widget_area menu-bar]
- [do_widget id="search-3"]
- [do_widget_area sidebar]
- [do_widget id="search-4"]
- [do_widget id="ai_widget-2"]
- [do_widget id="categories-5"]
- [do_widget id="ai_widget-3"]
- [do_widget id="ai_widget-4"]
- [do_widget id="ai_widget-5"]
- [do_widget_area sub-footer-1]
- [do_widget id="text-4"]
- [do_widget_area sub-footer-2]
- [do_widget_area sub-footer-3]
- [do_widget_area sub-footer-4]
- [do_widget_area upper-footer-1]
- [do_widget id="search-2"]
- [do_widget id="recent-posts-2"]
- [do_widget id="recent-comments-2"]
- [do_widget id="archives-2"]
- [do_widget id="categories-2"]
- [do_widget id="meta-2"]
- [do_widget_area upper-footer-2]
- [do_widget_area upper-footer-3]
- [do_widget_area upper-footer-4]
- [do_widget_area widgets_for_shortcodes]
- [do_widget id="search-5"]
- [do_widget id="ai_widget-6"]
- [do_widget_area wp_inactive_widgets]
- [do_widget id="wpp-2"]
- [do_widget id="text-1"]
- [do_widget id="recent-posts-3"]
- [do_widget id="categories-3"]
- [do_widget id="archives-3"]
- [do_widget id="icl_lang_sel_widget-3"]
Código fuente de los scripts de respaldo y restauración
Puedes encontrar el código fuente de ambos scripts en mi repositorio de Github daniloaz/myphp-backup: https://github.com/daniloaz/myphp-backup.
Y nada más. Si se te ocurre alguna característica adicional que pueda ser útil y eches en falta no dudes en dejarme un comentario. ¡Suerte!
47 comentarios
Unirte a la conversaciónCarlos Andrés Restrepo - 28/08/2012
Hola me funciono perfecto en un crontab solo un detalle retire de la linea $handle = fopen($outputDir.’/db-backup-‘.$this->dbName.’-‘.date(«Ymd-His», time()).’.sql’,’w+’);
la variable $outputDir dado que agrega un directorio de nombre cache y se pierde la ruta
pero funciona de lujo + 10
ya solo falta meterle los detallitos que uno considere que hagan falta para cada necesidad especifica
saludos
JOSE PASTOR - 07/09/2012
El script para hacer copia de la base de Datos me parece magnifico, por favor me pueden colaborar con el script para restaurar la base de Datos a partir del archivo creado con el script Backup_Databese.php
Les quedo altamente agradecido
Daniel - 03/10/2012
Muchas gracias José. Lamentablemente en este momento no dispongo de tiempo para publicar el script de restauración. No obstante, tengo intención de hacerlo. Lo subiré tan pronto como pueda. Un saludo.
Pierre - 25/11/2012
Por favor, quien me puede a ayudar a restaurar mi base de datos ?
Gracias de ante mano !
Pierre - 25/11/2012
Hola, por favor quien puede decir porque tengo este error al intentar respaldar mi base de datos
Deprecated: Function ereg_replace() is deprecated in C:xampphtdocsictvttrespaldarbackup.php on line 133
Daniel - 27/11/2012
Gracias por tu comentario Pierre, pero en realidad no se trata de un mensaje de error. Menciono la causa de ese mensaje en este mismo hilo, unos cuantos comentarios más arriba.
leonardo - 05/09/2014
ayuda por favor se realizó bien el respaldo pero no se como encontrarlo mas o menos entiendo q esta en la cache …ayuda
Daniel - 05/09/2014
El destino del respaldo se indica en la constante OUTPUT_DIR definida al principio del script. En mi caso era en el directorio cache, pero este directorio no tiene por qué existir en todas las instalaciones donde hagais funcionar el script. Por tanto, debes poner un directorio que sea válido en tu escenario concreto.
Martin - 05/02/2013
Hola Daniel, que pasa con valores NULL?, los escribe como «»?
Daniel - 02/04/2013
Hola Martin. Pues sinceramente no lo sé, no lo he probado con valores nulos… 🙂
Este script lo escribí para un trabajo puntual con un par de bases de datos específicas de un cliente y no se dio el caso que comentas. Es seguro que mi script es bastante mejorable aún. De hecho gracias a comentarios como el tuyo podré ir afinándolo más para que sea de utilidad a más personas. El problema es que no encuentro el tiempo necesario para hacerlo… 🙁
Si pudieras publicar el cambio que sería necesario hacer para corregir el problema te estaría muy agradecido, al igual que todos los lectores de tu comentario 😉
¡Gracias!
Fernando - 22/03/2013
Hola, agradecido por tu script. buen trabajo.
Te comento algunas cosas para quien llegue como yo a éste blog, pueda estar corregido.
– El nombre del constructor de la clase, debe llamarse __construct()
– El aviso que da de ereg_replace, se puede sustituir por str_replace.
Y creo que lo más importante, es que tu código exporta los datos a un fichero sql pero no tiene en cuenta las relaciones, por lo que para exportar está muy bien, pero para importarlo no es válido.
Por lo demás, buen trabajo. Perfecto.
Saludos y gracias por compartir tus conocimientos!
Daniel - 02/04/2013
Gracias Fernando por tus aportaciones. Efectivamente, hay algunas cosas que se han quedado anticuadas en mi script, como el uso de ereg_replace y el nombre del constructor, que debe llamarse __construct() en PHP5, aunque por compatibilidad con versiones anteriores se siga aceptando el nombre de la propia clase.
Tengo pendiente hacer varias mejoras e implementar una nueva clase para realizar importaciones y para aceptar tablas InnoDB con sus relaciones y demás, pero lamentablemente no he encontrado el momento por falta de tiempo.
Tendré en cuenta tu comentario para esa futura versión. Gracias.
Omar Hernandez - 09/04/2013
Excelente Script, funciona a la perfeccion.
felix - 09/07/2013
hola esta muy bien tu código, pero no me funciona cuando tengo tablas relacionadas….
alex - 18/07/2013
por alguna razon no me carga nada con un base de datos en especifico, sabes que pudo haber pasado?
que tenga algun tipo de proteccion o algo parecido?
Berdejo Humberto - 14/08/2013
Al restaurar el archivo sql los acentos y caracteres Ñ o ñ desaparecen y truncan la cadena en MySQL ¿Sabes a que se debe?
Bruce - 03/10/2013
Funciona perfectamente,its a perfect work thank you so much
Roberto Carlos Garcia Andino - 02/11/2013
Gracias, me sirvió tu código, tuve que agregarle una línea encima de tu línea 108 y concatenar la siguente:
$sql = «nn»;
$sql .= ‘CREATE DATABASE IF NOT EXISTS ‘.$this->dbName.»;nn»;
pues a la hora de leer los datos con la función file() me pone dos caracteres al inicio y es necesario separarlos de la primera línea sql. Espero este código le sirva a alguien más. Saludos.
$url = «db-backup-nominaplus-20131102-083116.sql»;
$nowhost = «localhost»;
$nowdatabase = «nominaplus1»;
$nowuser = «root»;
$nowpass = «»;
$link = mysql_connect($nowhost, $nowuser, $nowpass);
$lines = file($url);
foreach ($lines as $line_num => $line) {
echo «Line #{$line_num} : » . $line . «n»;
mysql_query($line);
}
Rama - 03/09/2014
Hola, en algunos casos me informa que todas las tablas las pasa OK pero luego crea el archivo con longitud cero … y no informa ningun error
zarith - 23/09/2014
Muchas gracias amigo, me funciono muy bien. Solo que gustaria que el archivo se descargara al escritorio o a la carpeta de descargas del computador para que sea mas fácil para el cliente ubicarlo. Espero pueda ayudarme con eso. Gracias de antemano.
Daniel - 23/09/2014
Lo siento, pero no es así como funciona. El script se ejecuta en el servidor y deja el resultado en el servidor para ser recogido mediante FTP. No obstante, gracias por la sugerencia. Lo tendré en cuenta como una mejora en la revisión del código que tengo pendiente.
pandorasoft - 09/10/2014
Hola, todos los resultados aparecen ok, pero el archivo que crea es ta a 0. ¿que puede ser?
Daniel - 09/10/2014
Pues no te sabría decir, habría que meter un poco de código de depuración en el script e ir viendo si el valor de la variable $sql se queda vacío y por qué. Sin algo más de información no te puedo decir qué ocurre.
Antonio Munguia - 20/02/2015
Hola Daniel buen script muy útil, una pregunta, en: define(«TABLES», ‘*’); el asterisco * significa que respaldara todas las tablas de la base de datos que tu elijas, o se tienen que poner el nombre de las tablas de la bd, muchas gracias por tu tiempo, y sigue así….
Mariana - 11/08/2015
Muy buen script! Yo necesité hacer unos cambios, para conseguir un formato como el de phpmyadmin. No sé si es lo más correcto, pero a mí me funcionó así:
$row[$j] = str_replace( array(«r», «n») , array(‘\r’, ‘\n’) , $row[$j] );
Por empezar, cambié ereg_replace por str_replace, (que daba error en las versiones nuevas de PHP). Y pasé un array con las distintas formas en que puede venir guardado el salto de línea.
Usé comillas dobles en el primer argumento y simples en el segundo, porque necesito que el primero interprete los saltos de línea y el segundo los escriba como string. Como estaba en tu script me interpretaba los saltos de línea en el documento, en lugar de mostrarlos como string.
Mariana - 11/08/2015
Me olvidé, en el comentario anterior, de agregar las tabulaciones, quedaría así:
$row[$j] = str_replace( array(«r», «n», «t») , array(‘\r’, ‘\n’, ‘\t’) , $row[$j] );
Diego Soto - 28/01/2016
El presente es una actualización del excelente artículo de Daniel Lopez Azaña quien se merece todos los créditos por el trabajo.
Lo que yo hice fue recopilar e incorporar todas las sugerencias propuestas por los que comentaron en el blog original y agregué de mi parte la especificación de la zona horaria para que el archivo de backup tenga el nombre acorde a la hora real de la zona.
Muchas gracias.
http://disientoconusted.blogspot.com.ar/2016/01/backup-de-bases-de-datos-mysql-con-php.html
This is an update of the excellent article by Daniel Lopez Azana, who deserves all the credit for the work.
What I did was collect and incorporate all suggestions made by those who commented on the original blog, and added specifying the time zone in order the backup file has the name according to the real time in your zone.
Thank you very much.
mario - 07/04/2016
como hago para hacer un respaldo de todas mis bases de datos
Daniel - 05/05/2016
Me temo que con el script actual sólo puedes hacerlo una a una cambiando los datos de conexión que aparecen al principio.
Jorge - 12/04/2016
Excelente, no pudo hacer respaldo de todas mis tablas, se terminaba la memoria, no sé si de php o de mysql, pero hice un loop y lo tengo en un conjob, me ahorraste mucho tiempo. Gracias.
Jorge Alejandro - 16/12/2016
Muchas Gracias por este aporte Ing. Luego se ve la gente que se apasiona de verdad por la programación. Unos libros que me recomiendes de php y mysql
Daniel - 17/12/2016
Gracias Jorge Alejandro. Echa un vistazo a este enlace para lo de los libros: https://www.cloudways.com/blog/best-books-to-help-you-learn-php/
Priyankar Gayen - 21/02/2017
fopen(cache/db-backup-ship_software-20170221-114447.sql) [function.fopen]: failed to open stream: No such file or directory in C:xampphtdocsship_softwaredatabase_bckup.php on line 182
Aldo - 30/04/2017
Hola Daniel gracias por el script funciona todo bien pero si necesito realizar el backup incluido los procedimientos, vistas, funciones, etc. que lo podría agregar al script? porque hasta ahora solo me devuelve las tablas.
ralph - 23/01/2018
excelente aporte, funciona muy bien
claro y preciso
saludos
Natsumi Franco - 14/03/2018
Buen día, estoy implementando el código pero me sale el error ob_flush(): failed to flush buffer. Si se hace el back up en el servidor y si lo descargo desde el servidor y al abrirlo me salen los datos.
En un sitio web creo un listado de todos los respaldo con la opción de descargar pero al intentar descargarlo me dice » Error: Ningún archivo encontrado» a alguien le ha pasado?
Joseph - 12/04/2018
Hola Natsumi
Vieras que me pasa lo mismo con el código, en mi localhost sale sin problema pero en el servidor me sale el error ob_flush(): failed to flush buffer, si hace los backups bien y baje el ultimo backup hecho y el archivo generado sale bien.
Pero me preocupa ese error que me sale de ob_flush(): failed to flush buffer
Que puede ser
Joseph - 16/03/2018
Hola Daniel
Excelente el código… me sirvió a la perfección, oye una consulta.. como se haría para que el código se ejecute cada día, por ejemplo ??
Daniel - 17/03/2018
Puedes usar cron en el propio servidor donde se vaya a hacer el backup ejecutando el script desde la línea de comandos, ya que este script de backup permite ser ejecutado indistintamente vía web a través de Apache o Nginx, o directamente desde la línea de comandos. Si no tienes acceso al cron del servidor puedes añadir una función que se ejecute cada vez que alguien visita una página de tu sitio y que compruebe la fecha y la hora, y si es aquella que tú has programado, entonces que ejecute el script. Es algo parecido a lo que hace el wp_cron de WordPress. Otra opción si no tienes acceso al servidor es programar mediante el cron de un ordenador al que sí tengas acceso una petición por medio de curl a la URL del script a la hora convenida.
Yosmar - 28/12/2018
El restore no me funciona me arroja el siguiente mensaje:
2018-12-28 06:46:16 – Gunzipping backup file myphp-backup-files/myphp-backup-your_db_name-20181022_164459.sql.gz…
Warning: gzopen(myphp-backup-files/myphp-backup-your_db_name-20181022_164459.sql.gz): failed to open stream: No such file or directory in C:\xampp\htdocs\sicpad\config\respaldos\myphp-restore.php on line 185
ERROR: couldn’t gunzip backup file myphp-backup-files/
2018-12-28 06:46:16 – Restoration result: KO
Daniel - 08/01/2019
Asegúrate de que exista el fichero myphp-backup-your_db_name-20181022_164459.sql.gz en una carpeta llamada myphp-backup-files dentro de la carpeta donde está el script de restauración myphp-restore.php. Es decir, en tu caso debe existir el fichero C:\xampp\htdocs\sicpad\config\respaldos\myphp-backup-files\myphp-backup-your_db_name-20181022_164459.sql.gz y además debe ser un fichero válido generado con el otro script myphp-backup.php y comprimido con gzip.
Alejandro Calderón Girón - 28/06/2019
Muchisimas gracias me ha funcionado perfectamente. saludos!!!!
Ant - 17/09/2019
como podria traducirse el script de mysqli a PDO??
Marbel - 10/12/2019
Extrae la BD pero no utilizarlo otra vez osea que no puedo ver ni importar a otra BD
alguien tubo el mismo problema
Francisco - 27/12/2019
y como puedo respaldar también las vistas, procedimientos y triggers??? Ojalá me puedan ayudar
Daniel - 20/01/2020
En este momento mi script no permite hacer backup de vistas, procedimientos y triggers. Para ello deberás usar una herramienta más sofisticada tipo mysqldump o phpMyAdmin.
Jamarchi - 20/01/2020
Hola, este código esta actualizado a la ultima versión de PHP ?
Saludos