Подтвердить что ты не робот

Исправить сериализованные данные, поврежденные из-за редактирования базы данных MySQL в текстовом редакторе?

Фон: Я загрузил резервную копию моей базы данных WordPress *.sql и заменил все экземпляры старого префикса таблицы базы данных на новый (например, по умолчанию wp_ на что-то вроде asdfghjkl_).

Я только что узнал, что WordPress использует сериализованные строки PHP в базе данных, и то, что я сделал, будет конфликтовать с целостностью сериализованных длин строк.

Дело в том, что я удалил файл резервной копии непосредственно перед тем, как я узнал об этом (так как мой сайт все еще функционировал нормально) и с тех пор установил несколько плагинов. Итак, я не могу вернуться назад, и поэтому я хотел бы знать две вещи:

  • Как я могу исправить это, если это вообще возможно?

  • Какие проблемы могут возникнуть?

(В этой статье говорится, что блог WordPress, например, может потерять настройки и виджеты. Но это, похоже, не со мной, настройки для моего блога все еще не повреждены, но я не знаю, что может быть нарушено внутри, или какие проблемы он будет представлять в будущем. Следовательно, этот вопрос.)

4b9b3361

Ответ 1

Посетите эту страницу: http://unserialize.onlinephpfunctions.com/

На этой странице вы увидите эту сериализованную строку: a:1:{s:4:"Test";s:17:"unserialize here!";}. Возьмите кусок его - s:4:"Test";. Это означает "строка", 4 символа, а затем фактическая строка. Я уверен, что то, что вы сделали, вызвало то, что числовое число символов не синхронизировано со строкой. Играйте с инструментом на сайте, упомянутом выше, и вы увидите, что вы получите сообщение об ошибке, если вы измените "Тест" на "Тес", например.

Что вам нужно сделать, чтобы эти символы совпадали с вашей новой строкой. Если вы не испортили какую-либо другую кодировку - удалили двоеточие или что-то еще, это должно устранить проблему.

Ответ 3

Я пришел к этой же проблеме после попытки изменить домен с localhost на реальный URL. После некоторого поиска я нашел ответ в документации Wordpress:

https://codex.wordpress.org/Moving_WordPress

Я приведу то, что там написано:

Чтобы избежать этой проблемы с сериализацией, у вас есть три варианта:

  • Используйте плагины улучшенного поиска или плагины обновлений Velvet Blues, если вы можете > получить доступ к своей панели мониторинга.
  • Используйте WP-CLI search-replace, если ваш хостинг-провайдер (или вы) установил WP-CLI.
  • Запустите поиск и замените запрос вручную в своей базе данных. Примечание. Выполняйте поиск и замену в таблице wp_posts.

В итоге я использовал WP-CLI, который может заменить вещи в базе данных без нарушения сериализации: http://wp-cli.org/commands/search-replace/

Ответ 4

Я знаю, что это старый вопрос, но лучше поздно, чем никогда, я полагаю. Недавно я столкнулся с этой проблемой, наследуя базу данных, в которой была найдена/заменена на сериализованные данные. После многих часов исследований я обнаружил, что это связано с тем, что количество строк не было. К сожалению, было так много данных с большим количеством экранов и новых строк, и я не знал, как рассчитывать в некоторых случаях, и у меня было так много данных, что мне было что-то автоматизировано.

По пути я наткнулся на этот вопрос, и сообщение Бенибурда помогло мне на правильном пути. Его примерный код не работал в производственных целях на сложных данных, содержащих многочисленные специальные символы и HTML, с очень глубокими уровнями вложенности, и он неправильно обрабатывал определенные экранированные символы и кодировку. Поэтому я немного изменил его и провел бесчисленные часы, работая с дополнительными ошибками, чтобы заставить мою версию "исправить" сериализованные данные.

// do some DB query here
while($res = db_fetch($qry)){
    $str = $res->data;
    $sCount=1; // don't try to count manually, which can be inaccurate; let serialize do its thing
    $newstring = unserialize($str);
    if(!$newstring) {
        preg_match_all('/s:([0-9]+):"(.*?)"(?=;)/su',$str,$m);
#           preg_match_all("/s:([0-9]+):(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")(?=;)/u",$str,$m); // alternate: almost works but leave quotes in $m[2] output
#           print_r($m); exit;
        foreach($m[1] as $k => $len) {
            /*** Possibly specific to my case: Spyropress Builder in WordPress ***/
            $m_clean = str_replace('\"','"',$m[2][$k]); // convert escaped double quotes so that HTML will render properly
            // if newline is present, it will output directly in the HTML
            // nl2br won't work here (must find literally; not with double quotes!)
            $m_clean = str_replace('\n', '<br />', $m_clean); 
            $m_clean = nl2br($m_clean);  // but we DO need to convert actual newlines also
            /*********************************************************************/
            if($sCount){
                $m_new = $m[0][$k].';'; // we must account for the missing semi-colon not captured in regex!
                // NOTE: If we don't flush the buffers, things like <img src="http://whatever" can be replaced with <img src="//whatever" and break the serialize count!!!                  
                ob_end_flush(); // not sure why this is necessary but cost me 5 hours!!
                $m_ser = serialize($m_clean);
                if($m_new != $m_ser) {
                    print "Replacing: $m_new\n";
                    print "With: $m_ser\n";
                    $str = str_replace($m_new, $m_ser, $str);
                }
            }
            else{
                $m_len = (strlen($m[2][$k]) - substr_count($m[2][$k],'\n'));
                if($len != $m_len) {
                    $newstr='s:'.$m_len.':"'.$m[2][$k].'"';
                    echo "Replacing: {$m[0][$k]}\n";
                    echo "With: $newstr\n\n";
                    $str = str_replace($m_new, $newstr, $str);
                }
            }
        }
        print_r($str); // this is your FIXED serialized data!! Yay!
    }
}

Немного уродливое объяснение моих изменений:

  • Я обнаружил, что попытка подсчета с кодом Benubird в качестве базы была слишком неточной для больших наборов данных, поэтому я просто использовал сериализацию, чтобы быть уверенным, что счет был точным.
  • Я избегал try/catch, потому что в моем случае попытка будет успешной, но просто вернет пустую строку. Таким образом, я проверяю вместо пустых данных.
  • Я пробовал множество регулярных выражений, но только мода на Benubird точно обрабатывала бы все случаи. В частности, мне пришлось изменить часть, которая проверила ";" потому что он будет соответствовать CSS как "width: 100%; height: 25px;" и сломал выход. Итак, я использовал позитивный взгляд, чтобы соответствовать только тогда, когда ";" был вне набора двойных кавычек.
  • В моем случае было много новых строк, HTML и экранированных двойных кавычек, поэтому мне пришлось добавить блок для очистки.
  • Было несколько странных ситуаций, когда данные будут неправильно заменены регулярным выражением, а затем сериализовать будет считать это неверно. Я не нашел НИЧЕГО на каких-либо сайтах, чтобы помочь с этим, и, наконец, подумал, что это может быть связано с кешированием или что-то в этом роде, и попытался очистить выходной буфер (ob_end_flush()), который работал, слава богу!

Надеюсь, это поможет кому-то... Принял меня почти 20 часов, включая исследования и проблемы со странными проблемами!:)

Ответ 5

Если ошибка связана с тем, что длина строк некорректна (что я часто видел), вы должны уметь адаптировать этот script, чтобы исправить ее:

foreach($strings as $key => $str)
{
    try {
        unserialize($str);
    } catch(exception $e) {
        preg_match_all('#s:([0-9]+):"([^;]+)"#',$str,$m);
        foreach($m[1] as $k => $len) {
            if($len != strlen($m[2][$k])) {
                $newstr='s:'.strlen($m[2][$k]).':"'.$m[2][$k].'"';
                echo "len mismatch: {$m[0][$k]}\n";
                echo "should be:    $newstr\n\n";
                $strings[$key] = str_replace($m[0][$k], $newstr, $str);
            }
        }
    }
}

Ответ 6

Мне лично не нравится работать на PHP или размещать мои учетные данные в публичном файле. Я создал ruby ​​ script для исправления сериализаций, которые вы можете запустить локально:

https://github.com/wsizoo/wordpress-fix-serialization

Редактирование контекста: Я применил сериализацию фиксации, сначала идентифицировав сериализацию с помощью регулярного выражения, а затем пересчитав размер байта содержащейся строки данных.

$content_to_fix.gsub!(/s:([0-9]+):\"((.|\n)*?)\";/) {"s:#{$2.bytesize}:\"#{$2}\";"}

Затем я обновляю указанные данные с помощью запроса на обновление sql-запроса.

escaped_fix_content = client.escape($fixed_content)

query = client.query("UPDATE #{$table} SET #{$column} = '#{escaped_fix_content}' WHERE #{$column_identifier} LIKE '#{$column_identifier_value}'")

Ответ 7

Этот script (https://interconnectit.com/products/search-and-replace-for-wordpress-databases/) может помочь обновить базу данных SQL с правильными URL-адресами везде, не сталкиваясь с проблемами сериализованных данных, потому что он обновит "количество символов", которое может вывести ваши URL-адреса из синхронизации, когда происходят сериализованные данные.

Этапы:

  • если вы уже импортировали испорченную базу данных (виджеты не рабочие, параметры темы не существуют и т.д.), просто отбросьте эту базу данных используя PhpMyAdmin. То есть, удалите все на нем. Затем экспорт и имеют под рукой не отредактированный дамп старой базы данных.

  • Теперь вам нужно импортировать (не отредактированную) старую базу данных в   вновь созданный. Вы можете сделать это с помощью импорта или копирования   db из PhpMyAdmin. Обратите внимание, что до сих пор мы не сделали никаких   искать и заменять; у нас просто есть старое содержимое базы данных и   структуру в новую базу данных со своим собственным пользователем и паролем. Возможно, на данный момент ваш сайт будет недоступен.

  • Убедитесь, что ваши файлы WordPress загружены в       правильной папке на сервере и отредактируйте свой wp-config.php, чтобы сделать это       подключиться к новой базе данных.
  • Загрузите script в "секретную" папку - только для обеспечения безопасности   причины - на том же уровне, что и wp-admin, wp-content и wp-includes. Не забудьте удалить все после поиска и   произошли изменения, поскольку вы рискуете предложить свои данные БД   открыт для всего Интернета.
  • Теперь укажите браузер в секретную папку и используйте script fine       интерфейс. Это очень самоочевидно. После использования мы переходим к       полностью удалите его с сервера.

Это должно привести к тому, что ваша база данных будет правильно обновлена ​​без каких-либо сериализованных проблем с данными: новый URL-адрес будет установлен повсеместно, и соответственно будут обновлены серийные символы символов.

Виджеты будут переданы, а также настройки темы - два из типичных мест, которые используют сериализованные данные в WordPress.

Готово и проверено решение!