简体   繁体   中英

How to dump MySQL table to a file then read it and use it in place of the DB itself?

because a provider I use, has a quite unreliable MySQL servers, which are down at leas 1 time pr week :-/ impacting one of the sites I made, I want to prevent its outeges in the following way:

  • dump the MySQL table to a file In case the connection with the SQL server is failed,
  • then read the file instead of the Server, till the Server is back.

This will avoid outages from the user experience point of view. In fact things are not so easy like it seems and I ask for your help please.

What I did is to save the data to a JSON file format. But this got issues because many data on the DB are "in clear" included escaped complex URLs, with long argument's line, that give some issue during the decode process from JSON. On CSV and TSV is also not workign correctly. CSV is delimited by Commas or Semilcolon , and those are present in the original content taken from the DB. TSV format leave double quotes that are not deletable, without avoid to go to eliminate them into the record's fields

Then I tried to serialize each record read from the DB, store it and retrive it serializing it. But the result is a bit catastrophic, becase all the records are stored in the file. When I retrieve them, only one is returned. then there is something that blocks the functioning of the program (here below the code please)

require_once('variables.php');
require_once("database.php");
$file = "database.dmp";

$myfile = fopen($file, "w") or die("Unable to open file!");

$sql = mysql_query("SELECT * FROM song ORDER BY ID ASC");
    // output data of each row
    while ($row = mysql_fetch_assoc($sql)) {
    // store the record into the file
    fwrite($myfile, serialize($row));
    }
fclose($myfile);
mysql_close();


// Retrieving section
$myfile = fopen($file, "r") or die("Unable to open file!");

// Till the file is not ended, continue to check it
    while ( !feof($myfile) ) {
        $record = fgets($myfile); // get the record
        $row = unserialize($record); // unserialize it
        print_r($row); // show if the variable has something on it
     }
fclose($myfile);

I tried also to uuencode and also with base64_encode but they were worse choices.

Is there any way to achieve my goal?

Thank you very much in advance for your help

If you have your data layer well decoupled you can consider using SQLite as a fallback storage.

It's just a matter of adding one abstraction more, with the same code accessing the storage and changing the storage target in case of unavailability of the primary one.

-----EDIT----- You could also try to think about some caching (json/html file?!) strategy returning stale data in case of mysql outage.

-----EDIT 2----- If it's not too much effort, please consider playing with PDO , I'm quite sure you'll never look back and believe me this will help you structuring your db calls with little pain when switching between storages.

Please take the following only as an example, there are much better way to design this architectural part of code.

Just a small and basic code to demonstrate you what I mean:

class StoragePersister
{
    private $driver = 'mysql';

    public function setDriver($driver)
    {
        $this->driver = $driver;
    }

    public function persist($data) 
    { 
        switch ($this->driver)
        {
            case 'mysql':
                $this->persistToMysql($data);
            case 'sqlite':
                $this->persistToSqlite($data);
        }
    }

    public function persistToMysql($data)
    {
        //query to mysql
    }

    public function persistSqlite($data)
    {
        //query to Sqlite
    }

}

$storage = new StoragePersister;
$storage->setDriver('sqlite'); //eventually to switch to sqlite
$storage->persist($somedata); // this will use the strategy to call the function based on the storage driver you've selected.

-----EDIT 3----- please give a look at the " strategy " design pattern section, I guess it can help to better understand what I mean.

After SELECT... you need to create a correct structure for inserting data, then you can serialize or what you want. For example: You have a row, you could do that - $sqls[] = "INSERT INTO song (field1,field2,.. fieldN) VALUES(field1_value, field2_value, ... fieldN_value);"; Than you could serialize this $sqls , write into file, and when you need it, you could read, unserialize and make query.

Have you thought about caching your queries into a cache like APC ? Also, you may want to use mysqli or pdo instead of mysql (Mysql is deprecated in the latest versions of PHP).

To answer your question, this is one way of doing it.

  • var_export will export the variable as valid PHP code
  • require will put the content of the array into the $data variable (because of the return statement)

Here is the code :

$sql = mysql_query("SELECT * FROM song ORDER BY ID ASC");
$content = array();

// output data of each row
while ($row = mysql_fetch_assoc($sql)) {
    // store the record into the file
    $content[$row['ID']] = $row;
}
mysql_close();

$data = '<?php return ' . var_export($content, true) . ';';
file_put_contents($file, $data);

// Retrieving section
$rows = require $file;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM