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

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

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

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

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

  2. какие проблемы это может вызвать?

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

7 ответов


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

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

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


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

https://codex.wordpress.org/Moving_WordPress

Я процитирую что там написано:

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

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

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


попробуйте этот скрипт, который исправляет проблемы сериализации:

https://github.com/Blogestudio/Fix-Serialization


вместе кстати, я наткнулся на этот вопрос и пост Benubird помог поставить меня на правильный путь. Его пример кода не работал в производственном использовании на сложных данных, содержащих многочисленные специальные символы и 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, потому что в моем случае попытка будет успешной, но просто вернет пустую строку. Вместо этого я проверяю пустые данные.
  • Я пробовал многочисленные regex, но только мод на Benubird будет точно обрабатывать все случаи. В частности, мне пришлось изменить часть, которая проверила";", потому что она будет соответствовать CSS, как "ширина:100%; высота:25px;" и сломал выход. Итак, я использовал положительный lookahead, чтобы соответствовать только тогда, когда ";" был вне набора двойных кавычек.
  • в моем случае было много новых строк, HTML и экранированных двойных кавычек, поэтому мне пришлось добавить блок, чтобы очистить его.
  • было несколько странных ситуаций, когда данные будут заменены неправильно регулярным выражением, а затем сериализация будет считать его неправильно также. Я ничего не нашел на каких-либо сайтах, чтобы помочь с этим, и, наконец, подумал, что это может быть связано с кэшированием или чем-то подобным, и попытался очистить выходной буфер (ob_end_flush ()), который работал, слава богу!

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


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

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);
            }
        }
    }
}

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

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

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

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

затем я обновляю указанные данные через беглый запрос на обновление.

escaped_fix_content = client.escape($fixed_content)

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

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

шаги будут:

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

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

  3. убедитесь, что ваши файлы WordPress недавно загружены в правильная папка на сервере и отредактируйте wp-config.PHP, чтобы сделать это подключитесь к новой базе данных.
  4. загрузить скрипт в "секретную" папку-просто для безопасности причины-на том же уровне, что и wp-admin, wp-content и wp-includes. Не забудьте удалить все сразу поиск и замена произошла, потому что вы рискуете предложить свои данные БД открыт для всего интернета.
  5. теперь наведите браузер на секретную папку и используйте скрипт в порядке взаимодействие. Это само собой разумеется. После использования, мы приступаем к полностью удалите его с сервера.

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

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

готово и протестировано решение!