Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como obter estruturas de tabelas de um arquivo .frm usando PHP?


Sim, é possível recuperar pelo menos parte da informação. (Para benefício de outros leitores, o autor da pergunta já está ciente de que existem maneiras mais fáceis de obter os metadados da coluna).

O desafio é que os arquivos .frm não são tão bem documentados porque qualquer necessidade de decifrá-los pela comunidade em geral é bastante rara. Além disso, o formato dos arquivos pode variar de acordo com o sistema operacional.

No entanto, visualizando os arquivos com hexdump ou um utilitário semelhante, você pode ver parcialmente o que está acontecendo. Então você está melhor informado para ler os arquivos em um programa PHP e decodificar os dados binários brutos.

Eu fiz isso como um exercício há algum tempo e consegui recuperar o número de colunas, nomes de colunas e tipos de colunas.

Abaixo está um exemplo para mostrar como extrair nomes de colunas. Meu .frm era para uma tabela com nomes "stops", mas você pode substituir seu próprio .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);

Isso deve fazer você começar. Vou acrescentar a isso quando tiver tempo nos próximos dias, se você acha que está indo na direção certa.

EDITAR. Atualizei o código para que funcione para qualquer arquivo .frm (da Tabela). Com certeza existe uma ferramenta gratuita para recuperar mySQL (baseada no mecanismo innoDB) disponível em https:/ /github.com/twindb/undrop-for-innodb . Depois de ler o código e os blogs associados, eles não estão usando os arquivos .FRM para recuperação. As mesmas informações da tabela também são armazenadas no dicionário innoDB e eles estão usando isso para recuperar formatos de tabela etc.

Há também uma maneira de ler o conteúdo dos arquivos .FRM. Isso descrito aqui https://twindb.com /how-to-recover-table-structure-from-frm-files-online/ . No entanto, eles estão usando o mySQL para ler os arquivos .frm e recriar as tabelas a partir deles.

Há também um utilitário um pacote de utilitários encontrado aqui https://www .mysql.com/why-mysql/presentations/mysql-utilities/ que contém um leitor .frm. Isso foi feito pela Oracle, que são as únicas pessoas que conhecem o formato dos arquivos .frm! O utilitário é gratuito para que você possa baixá-lo.

A Oracle publica algumas informações sobre o formato de arquivos .frm https://dev.mysql.com/doc/internals/en/frm-file-format.html , mas está incompleto e incorreto! Veja esta pergunta anterior do Stack.https://dba.stackexchange.com/questions/208198/mysql-frm-file-format-how-to-extract-column-info

Agora, depois de tudo isso, se você ainda quiser tentar analisar os arquivos .frm por diversão ou para aprender, precisará ser paciente e gastar tempo desvendando uma estrutura bastante complicada. Se você quiser continuar tentando, tudo bem, mas me envie seu arquivo .FRM (para example@sqldat .com ) para que eu possa verificar e enviarei em alguns dias algum código PHP que extrairá algumas informações adicionais, como tipo de dados e tamanhos de exibição.