Исправить сериализованные данные, поврежденные из-за редактирования базы данных MySQL в текстовом редакторе?
Фон: Я загрузил резервную копию моей базы данных WordPress *.sql и заменил все экземпляры старого префикса таблицы базы данных на новый (например, по умолчанию wp_
на что-то вроде asdfghjkl_
).
Я только что узнал, что WordPress использует сериализованные строки PHP в базе данных, и то, что я сделал, будет конфликтовать с целостностью сериализованных длин строк.
Дело в том, что я удалил файл резервной копии непосредственно перед тем, как я узнал об этом (так как мой сайт все еще функционировал нормально) и с тех пор установил несколько плагинов. Итак, я не могу вернуться назад, и поэтому я хотел бы знать две вещи:
(В этой статье говорится, что блог WordPress, например, может потерять настройки и виджеты. Но это, похоже, не со мной, настройки для моего блога все еще не повреждены, но я не знаю, что может быть нарушено внутри, или какие проблемы он будет представлять в будущем. Следовательно, этот вопрос.)
Ответы
Ответ 1
Посетите эту страницу: http://unserialize.onlinephpfunctions.com/
На этой странице вы увидите эту сериализованную строку: a:1:{s:4:"Test";s:17:"unserialize here!";}
. Возьмите кусок его - s:4:"Test";
. Это означает "строка", 4 символа, а затем фактическая строка. Я уверен, что то, что вы сделали, вызвало то, что числовое число символов не синхронизировано со строкой. Играйте с инструментом на сайте, упомянутом выше, и вы увидите, что вы получите сообщение об ошибке, если вы измените "Тест" на "Тес", например.
Что вам нужно сделать, чтобы эти символы совпадали с вашей новой строкой. Если вы не испортили какую-либо другую кодировку - удалили двоеточие или что-то еще, это должно устранить проблему.
Ответ 2
Попробуйте этот script, который устраняет проблемы с сериализацией:
https://github.com/Blogestudio/Fix-Serialization
Ответ 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.
Готово и проверено решение!