修复由于在文本编辑器中编辑 MySQL 数据库而损坏的序列化数据?
Posted
技术标签:
【中文标题】修复由于在文本编辑器中编辑 MySQL 数据库而损坏的序列化数据?【英文标题】:Fix serialized data broken due to editing MySQL database in a text editor? 【发布时间】:2013-02-14 20:12:42 【问题描述】:背景:我下载了我的 WordPress 站点数据库的 *.sql 备份,并将旧数据库表前缀的所有实例替换为新实例(例如,从默认 wp_
为 asdfghjkl_
)。
我刚刚了解到 WordPress 在数据库中使用了序列化的 php 字符串,而我所做的事情会破坏序列化字符串长度的完整性。
问题是,我在得知这一点之前删除了备份文件(因为我的网站仍然运行良好),并从那以后安装了许多插件。因此,我无法恢复原状,因此我想知道两件事:
如果可能的话,我该如何解决这个问题?
这会导致什么样的问题?
(This article 表示,例如,WordPress 博客可能会丢失其设置和小部件。但这似乎并没有发生在我身上,因为我博客的所有设置都完好无损。但我不知道至于内部可能会损坏什么,或者将来会造成什么问题。因此提出了这个问题。)
【问题讨论】:
对于研究人员,请参阅这篇文章以纠正序列化字符串中的错误字节数。 ***.com/a/55074706/2943403 它比 Brandon Elliott 的更容易阅读,比 wsizoo 的更精致,并且比 Benubird 的不耐分号的 sn-p 更健壮。 【参考方案1】:访问此页面:http://unserialize.onlinephpfunctions.com/
在该页面上,您应该会看到这个示例序列化字符串:a:1:s:4:"Test";s:17:"unserialize here!";
。拿一块——s:4:"Test";
。这意味着“字符串”,4 个字符,然后是实际的字符串。我很确定您所做的事情导致数字字符计数与字符串不同步。使用上述网站上的工具,例如,如果将“Test”更改为“Tes”,您会看到出现错误。
您需要做的是让这些字符数与您的新字符串匹配。如果您没有损坏任何其他编码(删除冒号或其他内容),那么应该可以解决问题。
【讨论】:
感谢您的解释!发现问题后,我发现此代码再次更正序列化。检查***.com/a/38890855/2323296【参考方案2】:在尝试将域从 localhost 更改为真实 URL 后,我遇到了同样的问题。经过一番搜索,我在 Wordpress 文档中找到了答案:
https://codex.wordpress.org/Moving_WordPress
我将引用那里写的内容:
为避免该序列化问题,您有以下三种选择:
如果可以,请使用 Better Search Replace 或 Velvet Blues Update URLs 插件 > 访问您的仪表板。 如果您的托管服务提供商(或您)已安装 WP-CLI,请使用 WP-CLI 的搜索替换。 在您的数据库上手动运行搜索和替换查询。注意:仅对 wp_posts 表执行搜索和替换。
我最终使用了 WP-CLI,它能够在不破坏序列化的情况下替换数据库中的内容:http://wp-cli.org/commands/search-replace/
【讨论】:
谢谢。不知道为什么这没有引起更多关注。遇到了同样的问题,最后也使用了WP-CLI
。如果您有很多外观要改变,这是最简单的方法。
这正是我一直在寻找的,不确定旧版本,但使用 --precise 标志是关键。【参考方案3】:
我知道这是一个老问题,但我想迟到总比没有好。我最近遇到了这个问题,在继承了一个对序列化数据执行了查找/替换的数据库之后。经过几个小时的研究,我发现这是因为字符串计数关闭了。不幸的是,有太多的数据有很多转义和换行符,在某些情况下我不知道如何计算,而且我有太多的数据,我需要一些自动化的东西。
在此过程中,我偶然发现了这个问题,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 个小时,包括研究和处理奇怪的问题! :)
【讨论】:
您能否为 Windows 制作一个可执行文件,该文件具有在 SQL 文件中搜索和替换字符串的选项?或者至少是一个 PHP 文件,您可以在其中指定源文件、目标文件、搜索字符串和替换字符串。 这个怎么用? 我的 IDE 说 $m_new 没有为字符串定义 $str = str_replace($m_new, $newstr, $str);【参考方案4】:此脚本 (https://interconnectit.com/products/search-and-replace-for-wordpress-databases/) 可以帮助在任何地方使用正确的 URL 更新 sql 数据库,而不会遇到序列化数据问题,因为它会更新“字符数”,这可能会在出现序列化数据时使您的 URL 不同步。
步骤如下:
如果您已经导入了一个混乱的数据库(小部件不是 工作,主题选项不存在等),只需删除该数据库 使用 PhpMyAdmin。也就是说,删除上面的所有内容。然后导出并 手头有一个未经编辑的旧数据库转储。
现在您必须将(未编辑的)旧数据库导入 新创建的一个。您可以通过导入或复制来执行此操作 来自 PhpMyAdmin 的数据库。请注意,到目前为止,我们还没有做任何 搜索和替换呢;我们只有一个旧的数据库内容和 用自己的用户名和密码构建一个新的数据库。此时您的网站可能无法访问。
确保您的 WordPress 文件刚刚上传到 服务器上的正确文件夹,然后编辑您的 wp-config.php 以使其 连接新数据库。 将脚本上传到“秘密”文件夹 - 只是为了安全 原因 - 与 wp-admin、wp-content 和 wp-includes 处于同一级别。搜索后不要忘记将其全部删除 替换已经发生,因为您冒着提供数据库详细信息的风险 对整个互联网开放。 现在将浏览器指向秘密文件夹,然后使用脚本即可 界面。这是非常不言自明的。使用后,我们继续 将其从服务器中彻底删除。这应该可以正确更新您的数据库,而不会出现任何序列化数据问题:新的 URL 将在各处设置,序列化数据字符数将相应更新。
将传递小部件和主题设置 - WordPress 中使用序列化数据的两个典型位置。
已完成并经过测试的解决方案!
【讨论】:
【参考方案5】:如果错误是由于字符串长度不正确(我经常看到的),那么您应该能够修改此脚本来修复它:
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 脚本来修复可以在本地运行的序列化:
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'")
【讨论】:
你能总结一下方法并在这里发布一些代码吗?链接本身不是答案,它们可能会中断或删除其内容。 谢谢@brichins!对此仍然很陌生...已编辑以提供上下文。以上是关于修复由于在文本编辑器中编辑 MySQL 数据库而损坏的序列化数据?的主要内容,如果未能解决你的问题,请参考以下文章
PHP:我利用富文本编辑器Ueditor编辑了一些内容,这些内容存储在Mysql中...
2022-10-08(Discuz漏洞FCKeditor文本编辑器漏洞ZooKeeper 未授权访问Memcahe 未授权访问)