终极MySQL遗留数据库噩梦

The ultimate MySQL legacy database nightmare

提问人:Mike Trader 提问时间:9/19/2008 更新时间:11/23/2008 访问量:2377

问:

表1: 一切都很好,包括厨房水槽。日期格式错误(年份为最后一年,因此无法对该列进行排序)、存储为 VARCHAR 的数字、“街道”列中的完整地址、firstname 列中的名字和姓氏、lastname 列中的城市、地址不完整、根据多年来更改的一组规则将数据从一个字段移动到另一个字段来更新前面行的行, 重复记录、不完整记录、垃圾记录......你的名字......哦,当然看不到 TIMESTAMP 或 PRIMARY KEY 列。

表2: 在打开这个婴儿后,任何正常化的希望都消失了。 我们为每个条目各行,并更新表一中的行。因此,像没有明天(价值 800MB)这样的重复项和像 Phone1、Phone2、Phone3、Phone4 这样的列......Phone15(它们不称为电话。我用它来说明)外键是..好吧,猜猜看。根据表 1 中行中的数据类型,有三个候选对象

表3: 情况会变得更糟吗?哦,是的。 “外键是破折号、点、数字和字母的 VARCHAR 列组合!如果这不能提供匹配(通常不提供匹配),那么类似的产品代码的第二列应该。名称与其中的数据无关的列,以及强制性的 Phone1 Phone2 Phone3 Phone4...电话15.有 Duplicated from Table1 列,但看不到 TIMESTAMP 或 PRIMARY KEY 列。

表4:被描述为一项进展中的工作,随时可能发生变化。它与其他人本质上相似。

在接近 1m 的行中,这是一个很大的混乱。幸运的是,这不是我的大烂摊子。不幸的是,我不得不从中为每个“客户”提取一个合成记录。

最初,我设计了 Table1 的四步转换,添加一个 PRIMARY KEY 并将所有日期转换为可排序的格式。然后,再进行几个步骤的查询,返回筛选后的数据,直到我有 Table1,我可以使用它从其他表中提取以形成合成。经过数周的工作,我使用一些技巧将其简化为一步。因此,现在我可以将我的应用程序指向混乱的地方,并拉出一个干净的合成数据表。幸运的是,我只需要其中一个电话号码来满足我的目的,因此规范我的表不是问题。

然而,这才是真正的任务开始的地方,因为每天都有数百名员工以你不想想象的方式添加/更新/删除这个数据库,每天晚上我都必须检索新行。

由于任何表中的现有行都可以更改,并且由于没有 TIMESTAMP ON UPDATE 列,因此我将不得不求助于日志来了解发生了什么。当然,这是假设存在二进制日志,但不存在!

引入这个概念就像铅气球一样下降。我还不如告诉他们,他们的孩子将不得不接受实验性手术。它们并不完全是高科技......万一你没有聚集......

情况有点微妙,因为他们有一些有价值的信息,我的公司非常想要。我被一家大公司的高级管理层(你知道他们是怎么回事)派去“实现它”。

我想不出任何其他方法来处理夜间更新,而不是使用另一个应用程序解析 bin 日志文件,以弄清楚他们在白天对该数据库做了什么,然后相应地合成我的表。我真的只需要看看他们的桌子1,就知道该对我的桌子做什么。其他表仅提供用于刷新记录的字段。(使用 MASTER SLAVE 无济于事,因为我会有一堆乱七八糟的东西。

另一种方法是为其 table1 的每一行创建一个唯一的哈希值,并构建一个哈希表。然后,我每天晚上都会检查整个数据库,看看哈希值是否匹配。如果他们没有,那么我会读取该记录并检查它是否存在于我的数据库中,如果存在,那么我会在我的数据库中更新它,如果没有,那么它是一条新记录,我会插入它。这很丑陋,而且速度不快,但解析二进制日志文件也不漂亮。

我写这篇文章是为了帮助弄清楚这个问题。通常告诉别人有助于澄清问题,使解决方案更加明显。在这种情况下,我只是更头疼!

您的想法将不胜感激。

MySQL 数据库 重构 binary-log

评论


答:

1赞 Matthias Kestenholz 9/19/2008 #1

您不能使用访问此数据库的现有代码并使其适应您的需求吗?当然,代码一定很糟糕,但它可能会为你处理数据库结构,不是吗?希望你可以专注于完成你的工作,而不是扮演考古学家。

0赞 MarkR 9/19/2008 #2

您也许可以使用 Maatkit 的 mk-table-sync 工具来同步临时数据库(毕竟您的数据库非常小)。这将“复制混乱”

然后,您可以编写一些东西,在同步后执行各种查询以生成一组更合理的表,然后可以报告这些表。

我想这可以每天完成,而不会出现性能问题。

在不同的服务器上执行所有这些操作将避免影响原始数据库。

我能看到的唯一问题是某些表是否没有主键。

评论

0赞 Mike Trader 9/20/2008
我能看到的唯一问题是某些表是否没有主键。- 他们没有...经过今天的更多会谈,他们告诉我他们“很少”更新/删除记录......不管这是什么意思。在与另一位数据库开发人员交谈时,似乎正确执行此操作的最佳(唯一)方法是对每一行进行哈希处理并将哈希值存储在表中。然后,每天晚上重新读取整个数据库,为每一行做一个哈希值,然后做一个简单的比较。我只是看不到解决它的方法。试图破译二进制日志文件只会充满危险。
2赞 Will Hartung 9/20/2008 #3

我不是MySQL人,所以这是从左边的字段出来的。

但我认为日志文件可能是答案。

值得庆幸的是,您真的只需要从日志中知道 2 件事。

您需要 record/rowid,并且需要操作。

在大多数数据库中,我假设是MySQL,每行都有一个隐式列,例如rowid或recordid,或其他什么。它是数据库使用的内部行号。这是您的“免费”主键。

接下来,您需要进行操作。值得注意的是,无论是对行执行插入、更新还是删除操作。

按时间顺序合并所有这些信息,然后运行它。

对于每次插入/更新,从原始数据库中选择行,然后在目标数据库中插入/更新该行。如果是删除,则删除该行。

你不关心字段值,它们并不重要。做整行。

希望您不必“解析”二进制日志文件,MySQL已经必须有例程来做到这一点,您只需要找到并弄清楚如何使用它们(甚至可能有一些方便的“转储日志”实用程序您可以使用)。

这使您可以保持系统非常简单,并且它应该只取决于您在一天中的实际活动,而不是总数据库大小。最后,您以后可以通过使其“更智能”来优化它。例如,也许他们插入一行,然后更新它,然后删除它。你会知道你可以在重播中完全忽略那一行。

显然,这需要一些神秘的知识才能实际读取日志文件,但其余的应该很简单。我想日志文件也有时间戳,所以你可以知道“从今天开始”处理行,或者你想要的任何日期范围。

1赞 Mike Trader 11/23/2008 #4

日志文件(二进制日志)也是我的第一个想法。如果你知道他们是怎么做事的,你会不寒而栗。对于每一行,日志中都有许多条目,因为添加和更改了各个部分。它简直是巨大的! 现在,我选择了哈希方法。通过一些巧妙的文件内存分页,这是相当快的。