1

I use the mysqldump to make a backup of my database. My database was destroyed by an accident and now I want to restore it. But the SQL file is double encoded by bug#28969. http://bugs.mysql.com/bug.php?id=28969 Is there any solution for my data to go back? I only have the SQL file made by mysqldump. Thanks.


I got my data back. Thanks everyone.

By this way,

1.import the messy data

2.use sqldump as 'mysqldump -h "$DB_HOST -u "$DB_USER" -p"$DB_PASSWORD" --opt --quote-names --skip-set-charset --default-character-set=latin1 "$DB_NAME" > /tmp/temp.sql'

Reference

http://pastebin.com/iSwVPk1w

shk3
  • 63
  • 1
  • 7
  • What exactly is meant by "double utf-8"? The 2 bytes repeated or something else? A hex example of some of the 4 byte sequences would be very helpful. I'm guessing you may just need to write a quick script to scan the dump file and correct each UTF-8 sequence it finds. – Erik Nedwidek Jul 08 '11 at 14:57
  • The bug report indicates this may have been an issue with an older version of MySQL. Are you on a recent version? – AJ. Jul 08 '11 at 14:59
  • I'm sure you've also learned a best practice here. Always check your backups against a "burn system" so you know they are good before you need them for disaster recovery. Don't feel bad we've all been there. :D – Erik Nedwidek Jul 08 '11 at 14:59
  • @AJ, that is definitely something he (or his service provider) will need to do, but he's currently in a disaster recovery situation. He needs the currently corrupted data back. If the database was still on the server, he'd be able to update and create a new backup and be good to go. – Erik Nedwidek Jul 08 '11 at 15:03
  • Thanks everyone here. I got my data back. By this way, 1.import the messy data 2.use sqldump as 'mysqldump -h "$DB_HOST -u "$DB_USER" -p"$DB_PASSWORD" --opt --quote-names --skip-set-charset --default-character-set=latin1 "$DB_NAME" > /tmp/temp.sql' Reference http://pastebin.com/iSwVPk1w – shk3 Jul 08 '11 at 15:12
  • But I still do not know why 'iconv' can not decode the file directly. I just get it back via the mysqldump itself. – shk3 Jul 08 '11 at 15:16

3 Answers3

5

I got my data back. Thanks everyone.

By this way,

1.import the messy data

2.use sqldump as mysqldump -h "$DB_HOST -u "$DB_USER" -p"$DB_PASSWORD" --opt --quote-names --skip-set-charset --default-character-set=latin1 "$DB_NAME" > /tmp/temp.sql

Reference

#!/bin/bash -e

DB_HOST="$1"
DB_USER="$2"
DB_PASSWORD="$3"
DB_NAME="$4"


mysqldump -h "$DB_HOST -u "$DB_USER" -p"$DB_PASSWORD" --opt --quote-names \
    --skip-set-charset --default-character-set=latin1 "$DB_NAME" > /tmp/temp.sql

mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" \
    --default-character-set=utf8 "$DB_NAME" < /tmp/temp.sql
Cobra_Fast
  • 15,671
  • 8
  • 57
  • 102
shk3
  • 63
  • 1
  • 7
0

If Your DB contain correct Collation but full data in DB are Doubly Encoded then this will help you remember you only execute its once and take backup of your DB.

<?php
/**
 * DoublyEncodeCorrection.php
 *
 * NOTE: Look for 'TODO's for things you may need to configure.
 * PHP Version 5
 *
 */
ini_set('display_errors','1');
//error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
// TODO: Pretend-mode -- if set to true, no SQL queries will be executed.  Instead, they will only be echo'd
// to the console.
$pretend = true;

// TODO: Should SET and ENUM columns be processed?
$processEnums = false;

// TODO: The collation you want to convert the overall database to
$defaultCollation = 'utf8_general_ci';

// TODO Convert column collations and table defaults using this mapping
// latin1_swedish_ci is included since that's the MySQL default
$collationMap = array(
    'latin1_bin'        => 'utf8_bin',
    'latin1_general_ci' => 'utf8_general_ci',
    'latin1_swedish_ci' => 'utf8_general_ci'
);

$mapstring = '';
foreach ($collationMap as $s => $t) {
    $mapstring .= "'$s',";
}

$mapstring = substr($mapstring, 0, -1); // Strip trailing comma
//echo $mapstring;

// TODO: Database information
$dbHost = 'localhost';
$dbName = 'tina';
$dbUser = 'root';
$dbPass = 'root';

// Open a connection to the information_schema database
$infoDB = mysql_connect($dbHost, $dbUser, $dbPass);

mysql_select_db('information_schema', $infoDB);

// Open a second connection to the target (to be converted) database
$targetDB = mysql_connect($dbHost, $dbUser, $dbPass, true);
mysql_select_db($dbName, $targetDB);

if (!is_resource($targetDB)) {
    echo "Could not connect to db!: " . mysql_error();exit;
}

if (mysql_select_db($dbName, $targetDB) === FALSE) {
    echo "Could not select database!: " . mysql_error();exit;
}

//
// TODO: FULLTEXT Indexes
//
// You may need to drop FULLTEXT indexes before the conversion -- execute the drop here.
// eg.
//    sqlExec($targetDB, "ALTER TABLE MyTable DROP INDEX `my_index_name`", $pretend);
//
// If so, you should restore the FULLTEXT index after the conversion -- search for 'TODO'
// later in this script.
//

// Get all tables in the specified database
$tables = sqlObjs($infoDB,
    "SELECT TABLE_NAME, TABLE_COLLATION
     FROM   TABLES
     WHERE  TABLE_SCHEMA = '$dbName'");

foreach ($tables as $table) {
    $tableName      = $table->TABLE_NAME;
    $tableCollation = $table->TABLE_COLLATION;

    // Find all columns that aren't of the destination collation
    $cols = sqlObjs($infoDB,
        "SELECT *
         FROM   COLUMNS
         WHERE  TABLE_SCHEMA    = '$dbName'
            AND TABLE_Name      = '$tableName'
            ");

    $intermediateChanges = array();
    $finalChanges = array();

    foreach ($cols as $col) {

        // If this column doesn't use one of the collations we want to handle, skip it
        if (in_array($col->COLLATION_NAME, $collationMap)) {
            //echo "<pre>";print_r($col->COLUMN_NAME);exit;
           sqlExec($targetDB,"UPDATE $dbName.$tableName SET $col->COLUMN_NAME = CONVERT(CAST(CONVERT($col->COLUMN_NAME USING latin1) AS BINARY) USING utf8)") ;
        }
    }
}


/**
 * Executes the specified SQL
 *
 * @param object  $db      Target SQL connection
 * @param string  $sql     SQL to execute
 * @param boolean $pretend Pretend mode -- if set to true, don't execute query
 *
 * @return SQL result
 */
function sqlExec($db, $sql, $pretend = false)
{
    echo "$sql;\n";

    if ($pretend === false) {
        $res = mysql_query($sql, $db);
        //echo "<pre>";print_r($res);exit;
        $error = mysql_error($db);
        if ($error !== '') {
            print "!!! ERROR: $error\n";
        }

        return $res;
    }

    return false;
}

/**
 * Gets the SQL back as objects
 *
 * @param object $db  Target SQL connection
 * @param string $sql SQL to execute
 *
 * @return SQL objects
 */
function sqlObjs($db, $sql)
{
    $res = sqlExec($db, $sql);

    $a = array();

    if ($res !== false) {
        while ($obj = mysql_fetch_object($res)) {
            $a[] = $obj;
        }
    }

    return $a;
}

?> 
Bharat Parmar
  • 1,842
  • 2
  • 18
  • 22
0

If it's just doubling the UTF-8 bytes or prepending something, I'd suggest putting together a quick sed/awk command to match and correct them.

http://www.osnews.com/story/21004/Awk_and_Sed_One-Liners_Explained

If you're not comfortable with this, any scripting language with regex support could be used to easily do the same thing, though it might take a few more minutes.

kungphu
  • 4,592
  • 3
  • 28
  • 37
  • I am not sure if your answer can help. I have tried decode by 'iconv', but it does not give my data back. Luckily, I just find the resolution. Thanks for your help. – shk3 Jul 08 '11 at 15:14