Me parece que tu consulta plantea una cuestión interesante y valiosa. Es una pena que, como mencionas, hay quienes a causa de restricciones arbitrarias no pueden ejecutar comandos como
mysqldump aun teniendo acceso libre a bases de datos.
En cuanto a la generación de copias de respaldo, una solución efectiva es usar algún software de administración como el popular phpMyAdmin, pero dejando su uso de lado por un momento, lo que me ha parecido interesante de tu pregunta es pensar en la posibilidad de crear un mecanismo simple para exportar bases de datos usando los recursos disponibles, que en principio no ha de ser muy complicado, al menos para los casos más simples.
Así es que con algo de tiempo y paciencia escribí una sencilla función que intenta exportar bases de datos MySQL como sentencias SQL, almacenando sus resultados en un archivo externo. Está parcialmente basada en el modo en que opera la acción
Exportar en phpMyAdmin, aunque no re-usa código de ese proyecto. En cualquier caso, estudiar el código de una aplicación como phpMyAdmin vale la pena para aquellos interesados; dispone de montones de funcionalidad y se trata de una aplicación que es probada constantemente con éxito.
Bien, volviendo al ejercicio al que me refiero, este es el código:
Código PHP:
<?php
/********************
* Funcion auxiliar *
********************/
/**
* mysql_escapar_valor:
* @valor: Valor a escapar.
*
* Convierte un valor dado a una expresion apta para insertar en una base
* de datos MySQL.
*
* Valor de retorno: Valor convertido para MySQL.
**/
function mysql_escapar_valor ($valor)
{
if ($valor === NULL)
return 'NULL';
if (is_bool ($valor)) {
if ($valor)
return 1;
else
return 0;
}
if (is_numeric ($valor))
return $valor;
return '\'' . mysql_real_escape_string ($valor) . '\'';
}
/*********************
* Funcion principal *
*********************/
/**
* mysql_exportar:
* @id_enlace: Un identificador de enlace valido creado p.ej. por
* mysql_connect()
* @nombre_archivo: El nombre de un archivo en donde almacenar la
* salida SQL.
*
* Exporta una base de datos, en base a sentencias SQL capaces de
* re-crear y poblar las tablas de una base de datos dada. Los
* resultados son almacenados en el archivo con el nombre dado.
*
* Es necesario llamar mysql_select_db() antes de llamar esta funcion
* para especificar sobre que base de datos operar (y por ende cual
* base de datos exportar).
*
* Por el momento, esta funcion tiene una funcionalidad muy limitada,
* y es probable que contenga errores debido a falta de pruebas con
* buenos conjuntos de datos. Usese con precaucion :). Por otra parte,
* sientase libre de estudiarla y modificarla a su gusto.
*
* Valor de retorno: TRUE si la operacion tiene exito, o FALSE de lo
* contrario.
**/
function mysql_exportar ($id_enlace, $nombre_archivo)
{
// Aserciones
if (! is_resource ($id_enlace)) {
trigger_error ('mysql_exportar: No se ha entregado un recurso valido',
E_USER_ERROR);
return FALSE;
}
if (strpos (get_resource_type ($id_enlace), 'mysql') === FALSE) {
trigger_error ('mysql_exportar: El recurso dado no es un enlace MySQL',
E_USER_ERROR);
return FALSE;
}
// Obtener informacion de las tablas disponibles
$consulta = mysql_query ('SHOW TABLE STATUS', $id_enlace);
if ($consulta === FALSE) {
trigger_error ('mysql_exportar: No ha sido posible obtener ' .
'informacion de las tablas', E_USER_ERROR);
return FALSE;
}
$tablas = array ();
while (($fila = mysql_fetch_assoc ($consulta)) !== FALSE) {
$tablas[] = $fila;
}
$da = @fopen ($nombre_archivo, 'w');
if ($da === FALSE) {
trigger_error ('mysql_exportar: No ha sido posible crear el archivo ' .
'de salida ', E_USER_ERROR);
return FALSE;
}
// Bloquear mientras escribimos en el archivo
if (! flock ($da, LOCK_EX))
return FALSE;
// Procesar tablas individualmente
foreach ($tablas as $tabla) {
// Incluir un comentario antes de cada tabla
$cabecera = <<<FIN_CABECERA
--
-- Estructura de la tabla `{$tabla['Name']}`
--
FIN_CABECERA;
fwrite ($da, $cabecera);
// Sentencia CREATE TABLE
fwrite ($da, "CREATE TABLE `{$tabla['Name']}` (\n");
// Obtener columnas da la tabla
$consulta = mysql_query ("SHOW COLUMNS FROM {$tabla['Name']}",
$id_enlace);
$declaraciones = array ();
$decl_extra = array ();
while (($campo = mysql_fetch_assoc ($consulta)) !== FALSE) {
$decl_campo = " `{$campo['Field']}` {$campo['Type']}";
if ($campo['Null'] == '')
$decl_campo .= ' NOT NULL';
if ($campo['Default'] != '')
$decl_campo .= ' default ' .
mysql_escapar_valor ($campo['Default']);
if ($campo['Extra'] != '')
$decl_campo .= " {$campo['Extra']}";
if ($campo['Key'] == 'PRI')
$decl_extra[] = " PRIMARY KEY (`{$campo['Field']}`)";
$declaraciones[] = $decl_campo;
}
$declaraciones = array_merge ($declaraciones, $decl_extra);
fwrite ($da, implode (",\n", $declaraciones) . "\n");
// Cierre de CREATE TABLE
$propiedades = "TYPE={$tabla['Type']} ";
if ($tabla['Auto_increment'] !== NULL)
$propiedades .= "AUTO_INCREMENT={$tabla['Auto_increment']} ";
fwrite ($da, ") {$propiedades};\n");
// Incluir un comentario antes de volcar los datos
$cabecera = <<<FIN_CABECERA
--
-- Volcando datos para la tabla `{$tabla['Name']}`
--
FIN_CABECERA;
fwrite ($da, $cabecera);
// Sentencias INSERT
$consulta = mysql_query ("SELECT * FROM `{$tabla['Name']}`",
$id_enlace);
while (($fila = mysql_fetch_row ($consulta)) !== FALSE) {
$valores = array ();
for ($i = 0, $n = count ($fila); $i < $n; $i++)
$valores[] = mysql_escapar_valor ($fila[$i]);
fwrite ($da, "INSERT INTO `{$tabla['Name']}` VALUES (" .
implode (', ', $valores) . ");\n");
}
// Fin de la tabla
fwrite ($da, "\n\n-- -------------------------------\n\n");
}
// Desbloquear
if (! flock ($da, LOCK_UN))
return FALSE;
fclose ($da);
return TRUE;
}
/**************************************
* Ejemplo de uso de mysql_exportar() *
**************************************/
// Datos para conectarse con la base de datos
define ('BD_USUARIO', 'mi_usuario'); // Nombre de usuario
define ('BD_CONTRASENYA', 'mi_contrasenya'); // Contrasenya del usuario
define ('BD_HOST', 'localhost'); // Host del servidor MySQL
define ('BD_NOMBRE', 'nombre_bd'); // Nombre de la base de datos
// Nombre del archivo en donde almacenar la base de datos exportada
define ('ARCHIVO_SQL', 'bd.sql');
$enlace = mysql_connect (BD_HOST, BD_USUARIO, BD_CONTRASENYA);
if ($enlace === FALSE) {
echo "No ha sido posible conectarse con la base de datos\n";
exit (1);
}
$retval = mysql_select_db (BD_NOMBRE, $enlace);
if ($retval === FALSE) {
echo "No ha sido posible seleccionar la base de datos\n";
exit (1);
}
$retval = mysql_exportar ($enlace, ARCHIVO_SQL);
if ($retval === FALSE) {
echo "No ha sido posible exportar la base de datos a un archivo\n";
exit (1);
}
echo "La base de datos ha sido exportada.\n";
?>
No la he probado exhaustivamente, así que es bien posible que tenga problemas en ciertos casos especiales, pero puede que sirva como un inicio para quien desee corregirla/extenderla :).