Mysql
 sql >> Database >  >> RDS >> Mysql

Come ottenere le strutture delle tabelle da un file .frm usando PHP?

Sì, è possibile recuperare almeno una parte delle informazioni. (A beneficio di altri lettori, chi pone la domanda è già consapevole del fatto che esistono modi più semplici per ottenere i metadati delle colonne).

La sfida è che i file .frm non sono così ben documentati perché la necessità di decifrarli da parte della comunità generale è piuttosto rara. Anche il formato dei file può variare con il sistema operativo.

Tuttavia, visualizzando i file con hexdump o un'utilità simile puoi vedere in parte cosa sta succedendo. Quindi è meglio informarsi per leggere i file in un programma PHP e decodificare i dati binari grezzi.

L'ho fatto come esercizio qualche tempo fa e sono stato in grado di recuperare numero di colonne, nomi di colonne e tipi di colonne.

Di seguito è riportato un esempio per mostrare come estrarre i nomi delle colonne. Il mio .frm era per i nomi di una tabella "fermate", ma puoi sostituire il tuo .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);

Questo dovrebbe farti cominciare. Aggiungerò a questo quando avrò tempo nei prossimi giorni se ritieni che stia andando nella giusta direzione.

MODIFICA. Ho aggiornato il codice in modo che funzioni con qualsiasi file .frm (dalla tabella). Di sicuro esiste uno strumento gratuito per recuperare MySQL (basato sul motore innoDB) disponibile su https:/ /github.com/twindb/undrop-for-innodb . Dopo aver letto il codice e i blog associati, non utilizzano i file .FRM per il ripristino. Le stesse informazioni sulla tabella sono memorizzate anche nel dizionario innoDB e lo stanno usando per recuperare i formati delle tabelle, ecc.

C'è anche un modo per leggere il contenuto dei file .FRM. Questo è descritto qui https://twindb.com /come-recuperare-la-struttura-della-tabella-da-file-frm-online/ . Tuttavia, stanno usando MySQL per leggere i file .frm e ricreare le tabelle da lì.

C'è anche un'utilità un pacchetto di utilità trovato qui https://www.mysql.com/why-mysql/presentations/mysql-utilities/"> .mysql.com/why-mysql/presentations/mysql-utilities/ che contiene un lettore .frm. Questo è stato realizzato da Oracle, che sono le uniche persone che conoscono il formato dei file .frm! L'utilità è gratuita, quindi puoi scaricarla.

Oracle pubblica alcune informazioni sul formato dei file .frm https://dev.mysql.com/doc/internals/en/frm-file-format.html , ma è sia incompleto che errato! Vedi questa precedente domanda sullo stack.https://dba.stackexchange.com/questions/208198/mysql-frm-file-format-how-to-extract-column-info

Dopo tutto ciò, se vuoi ancora provare ad analizzare i file .frm da solo per divertimento o per apprendimento, devi essere paziente e dedicare del tempo a svelare una struttura piuttosto complicata. Se vuoi continuare a provare, va bene, ma inviami il tuo file .FRM ( a example@sqldat .com ) così posso verificarlo e in pochi giorni ti invierò del codice PHP che estrarrà alcune informazioni aggiuntive come il tipo di dati e le dimensioni del display.