修复由于在文本编辑器中编辑MySQL数据库而导致的序列化数据损坏?

时间:2013-02-28 15:08:05

标签: mysql wordpress mysqldump mariadb

后台:我下载了我的WordPress网站数据库的 * .sql 备份,并将旧数据库表前缀的所有实例替换为新的(例如来自默认wp_类似于asdfghjkl_)。

我刚刚了解到WordPress在数据库中使用了序列化的PHP字符串,而我所做的将与序列化字符串长度的完整性混淆。

问题是,我在了解此之前删除了备份文件(因为我的网站仍然正常运行),并且安装了许多插件。所以,我无法回复,因此我想知道两件事:

  1. 如果可能,我该如何解决这个问题?

  2. 这会导致什么样的问题?

  3. This article声称,例如,WordPress博客可能会丢失其设置和小部件。但这似乎并没有发生在我身上,因为我博客的所有设置仍然完好无损。但我有没有任何关于内部可能被打破的线索,或者未来会出现什么问题。因此这个问题。)

6 个答案:

答案 0 :(得分:15)

访问此页面:http://unserialize.onlinephpfunctions.com/

在该页面上,您应该看到此示例序列化字符串:a:1:{s:4:"Test";s:17:"unserialize here!";}。拿一块它 - s:4:"Test";。这意味着“字符串”,4个字符,然后是实际的字符串。我很确定你做了什么导致数字字符计数与字符串不同步。使用上述网站上的工具进行播放,例如,如果将“测试”更改为“测试”,您将看到错误。

您需要做的是获取与新字符串匹配的字符数。如果您没有损坏任何其他编码 - 删除冒号或其他东西 - 应该解决问题。

答案 1 :(得分:9)

在尝试将域名从localhost更改为真实URL后,我遇到了同样的问题。经过一番搜索后,我在Wordpress文档中找到了答案:

https://codex.wordpress.org/Moving_WordPress

我会引用那里写的内容:

  

要避免序列化问题,您有三个选择:

     
      
  • 如果可以,请使用更好的搜索替换或Velvet Blues更新网址插件。访问您的仪表板。
  •   
  • 如果您的托管服务提供商(或您)安装了WP-CLI,请使用WP-CLI的搜索替换。
  •   
  • 在数据库上手动运行搜索并替换查询。注意:仅在wp_posts表上执行搜索和替换。
  •   

我最终使用WP-CLI,它可以替换数据库中的内容而不会破坏序列化:http://wp-cli.org/commands/search-replace/

答案 2 :(得分:3)

我知道这是一个老问题,但我认为迟到总比没有好。在继承了在序列化数据上执行了find / replace的数据库之后,我最近遇到了这个问题。经过几个小时的研究,我发现这是因为字符串计数已经关闭。不幸的是,有太多的数据包含大量的转义和新行,我不知道在某些情况下如何计算,而且我有太多的数据需要自动化的东西。

一路上,我偶然发现了这个问题,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,因为在我的情况下,try会成功,但只返回一个空字符串。所以,我改为检查空数据。
  • 我尝试了很多正则表达式,但只有Benubird的一个mod才能准确处理所有情况。具体来说,我必须修改检查“;”的部分因为它会匹配CSS,如“width:100%; height:25px;”并打破了输出。所以,我用一个积极的前瞻只匹配“;”在双引号之外。
  • 我的案例有很多换行符,HTML和转义双引号,所以我不得不添加一个块来清理它。
  • 有一些奇怪的情况,正则表达式会错误地替换数据,然后序列化也会错误地计算它。我在任何网站上发现没有任何帮助,最后认为它可能与缓存或类似的东西有关,并试图刷新输出缓冲区(ob_end_flush()),这很有效,谢天谢地!

希望这可以帮助别人...花了近20个小时,包括研究和处理奇怪的问题! :)

答案 3 :(得分:1)

如果错误是由于字符串的长度不正确(我经常看到的),那么您应该能够调整此脚本来修复它:

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

答案 4 :(得分:1)

我个人不喜欢在PHP中工作,或者将我的数据库凭据放在公共文件中。我创建了一个ruby脚本来修复可以在本地运行的序列化:

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}'")

答案 5 :(得分:1)

这个脚本(https://interconnectit.com/products/search-and-replace-for-wordpress-databases/)可以帮助在任何地方使用正确的URL更新sql数据库,而不会遇到序列化的数据问题,因为它会更新“字符数”,这可能会在序列化数据时使您的URL不同步发生。

步骤如下:

  1. 如果您已经导入了混乱的数据库(小部件没有 工作,主题选项不存在,等),只需删除该数据库 使用PhpMyAdmin。也就是说,删除它上面的所有内容。然后导出和 手头有一个未经编辑的旧数据库转储。

  2. 现在你必须将(未经编辑的)旧数据库导入到     新创建的。您可以通过导入或复制来完成此操作     来自PhpMyAdmin的数据库。请注意,到目前为止,我们还没有做过     搜索和替换;我们只有一个旧的数据库内容和     使用自己的用户和密码将结构转换为新数据库。此时您的网站可能无法访问。

  3. 确保将新的WordPress文件上传到         服务器上的正确文件夹,并编辑你的wp-config.php来实现它         连接新数据库。
  4. 将脚本上传到“秘密”文件夹 - 仅为了安全起见     原因 - 与wp-admin,wp-content和wp-includes处于同一级别。一旦搜索和,请不要忘记将其全部删除     已经进行了替换,因为您有可能提供您的数据库详细信息     对整个互联网开放。
  5. 现在将您的浏览器指向秘密文件夹,并使用该脚本         接口。这是非常不言自明的。一旦使用,我们继续         将其从服务器中完全删除。
  6. 这应该正确更新您的数据库,没有任何序列化数据问题:新URL将在任何地方设置,并且序列化数据字符计数将相应更新。

    小部件将被传递,主题设置也是 - 在WordPress中使用序列化数据的两个典型位置。

    完成并经过测试的解决方案!