sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo obtener estructuras de tablas de un archivo .frm usando PHP?

Sí, es posible recuperar al menos parte de la información. (Para el beneficio de otros lectores, el autor de la pregunta ya sabe que hay formas más fáciles de obtener los metadatos de la columna).

El desafío es que los archivos .frm no están tan bien documentados porque la necesidad de descifrarlos por parte de la comunidad en general es bastante rara. Además, el formato de los archivos puede variar según el sistema operativo.

Sin embargo, al ver los archivos con hexdump o una utilidad similar, puede ver en parte lo que está sucediendo. Entonces es mejor que leas los archivos en un programa PHP y decodifiques los datos binarios sin procesar.

Hice esto como un ejercicio hace algún tiempo y pude recuperar la cantidad de columnas, los nombres de las columnas y los tipos de columnas.

A continuación se muestra un ejemplo para mostrar cómo extraer los nombres de las columnas. Mi .frm era para una tabla con el nombre "paradas", pero puede sustituirlo por su propio .frm.

<?php
$fileName = "stops.frm";

// read file into an array of char
//---------------------------------
$handle = fopen($fileName, "rb");
$contents = fread($handle, filesize($fileName));
fclose($handle);
$fileSize=strlen($contents);  // save the filesize fot later printing

// locate the column data near the end of the file
//-------------------------------------------------
$index = 6;    // location of io_size
$io_size_lo = ord($contents[$index]);  
$io_size_hi = ord($contents[$index+1]);
$io_size = $io_size_hi *0x100 + $io_size_lo; // read IO_SIZE

$index = 10;  // location of record length
$rec_len_lo = ord($contents[$index]);
$rec_len_hi = ord($contents[$index+1]);
$rec_len = $rec_len_hi * 0x100 + $rec_len_lo; // read rec_length

// this formula uses io_size and rec_length to get to column data
$colIndex = ( (  (($io_size + $rec_len)/$io_size)   + 1) * $io_size ) + 258;
$colIndex -= 0x3000;   // this is not documented but seems to work!

// find number of columns in the table
//------------------------------------------------- 
echo PHP_EOL."Col data at 0x".dechex($colIndex).PHP_EOL;
$numCols = ord($contents[$colIndex]);

//Extract the column names
//--------------------------------------
$colNameIndex = $colIndex+0x50;   //0X50 by inspection
echo "Col names at 0x".dechex($colNameIndex).PHP_EOL;
$cols=array();
for ($col = 0; $col < $numCols; $col++){
    $nameLen = ord($contents[$colNameIndex++]);          // name length is at ist posn
    $cols[]['ColumnName']= substr($contents,$colNameIndex,$nameLen-1); // read the name
    $colNameIndex+=$nameLen+2;        // skip ahead to next name (2 byte gap after \0)
}
print_r($cols);

Esto debería ayudarte a empezar. Agregaré a esto cuando tenga tiempo en los próximos días si crees que va en la dirección correcta.

EDITAR. Actualicé el código para que funcione para cualquier archivo .frm (de Table). Seguro que hay una herramienta gratuita para recuperar mySQL (basada en el motor innoDB) disponible en https:/ /github.com/twindb/undrop-for-innodb . Habiendo leído el código y los blogs asociados, no están usando los archivos .FRM para la recuperación. La misma información de la tabla también se almacena en el diccionario innoDB y lo utilizan para recuperar formatos de tabla, etc.

También hay una forma de leer el contenido de los archivos .FRM. Esto se describe aquí https://twindb.com /cómo-recuperar-la-estructura-de-una-tabla-desde-archivos-frm-online/ . Sin embargo, están usando mySQL para leer los archivos .frm y recrear tablas desde allí.

También hay una utilidad, un paquete de utilidades que se encuentra aquí https://www .mysql.com/por qué-mysql/presentations/mysql-utilities/ que contiene un lector .frm. ¡Esto fue hecho por Oracle, que son las únicas personas que conocen el formato de los archivos .frm! La utilidad es gratuita, por lo que puede descargarla.

Oracle publica información sobre el formato de los archivos .frm https://dev.mysql.com/doc/internals/en/frm-file-format.html , ¡pero es incompleto e incorrecto! Consulte esta pregunta anterior de Stack.>https://dba.stackexchange.com/questions/208198/mysql-frm-file-format-how-to-extract-column-info

Ahora, después de todo eso, si aún desea intentar analizar los archivos .frm usted mismo por diversión o para aprender, entonces debe ser paciente y dedicar tiempo a desentrañar una estructura bastante complicada. Si desea seguir intentándolo, está bien, pero envíeme su archivo .FRM (a example@sqldat .com ) para que pueda verificarlo y le enviaré un código PHP en unos días que extraerá información adicional como el tipo de datos y los tamaños de visualización.