最终MySQL遗留数据库的噩梦

时间:2008-09-19 12:06:31

标签: mysql database refactoring binary-log

表1: 一切包括厨房水槽。日期格式错误(年末,因此您无法对该列进行排序),存储为VARCHAR的数字,“street”列中的完整地址,firstname列中的firstname和lastname,lastname列中的city,不完整的地址,行数根据多年来发生变化的一些规则,重复记录,不完整记录,垃圾记录......将数据从一个字段移动到另一个字段,从而更新前面的行...您将其命名为...哦,当然不是TIMESTAMP或PRIMARY KEY栏目即将开始。

表2: 打开这个婴儿后,任何正常化的希望就会消失。 对于表1中的每个条目和行更新,我们都有一行。所以复制品就像没有明天(800MB价值)和像Phone1 Phone2 Phone3 Phone4 ... Phone15这样的列(它们不叫电话。我用它来说明)foriegn键是......好好猜测。根据表1中行的数据类型,有三个候选者

表3: 它会变得更糟吗?哦,是的。 “外键是短划线,点,数字和字母的VARCHAR列组合!如果不提供匹配(通常不提供),那么类似产品代码的第二列应该。具有名称的列与它们内部的数据无关,并且必须与Phone1 Phone2 Phone2 Phone3 Phone4 ... Phone15。从Table1复制列,而不是TIMESTAMP或PRIMARY KEY列。

表4:被描述为一项工作,并且随时可能发生变化。它与其他人相似。

接近1米行时,这是一个很大的混乱。幸运的是,这不是我的大混乱。不幸的是,我必须为每个“客户”提供一份复合记录。

最初,我设计了Table1的四步翻译,添加了一个PRIMARY KEY并将所有日期转换为可排序的格式。然后是几个返回过滤数据的查询步骤,直到我将Table1用于从其他表中拉出以形成合成。经过数周的工作,我使用一些技巧将其降低到一步。所以现在我可以将我的应用程序指向混乱并提取一个很好的合成数据表。幸运的是,我只需要一个电话号码,因此我的桌子正常化不是问题。

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

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

介绍这个概念就像铅球一样。我不妨告诉他们,他们的孩子将不得不接受实验性手术。他们并不完全是高科技......如果你没有聚集......

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

我无法想到处理夜间更新的任何其他方法,而不是使用另一个应用程序解析bin日志文件,以确定他们在白天对该数据库所做的事情,然后相应地合成我的表。我真的只需要看看他们的table1来弄清楚该怎么做我的桌子。其他表只提供清除记录的字段。 (使用MASTER SLAVE无济于事,因为我会有一塌糊涂。)

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

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

非常感谢您的想法。

4 个答案:

答案 0 :(得分:2)

我不是一个MySQL人,所以这是左边的领域。

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

谢天谢地,你真的只需要从日志中知道两件事。

您需要记录/ rowid,并且需要操作。

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

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

您按时间顺序合并所有这些信息,然后贯穿它。

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

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

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

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

显然,为了实际读取日志文件,这需要一些神秘的知识,但其余的应该是直截了当的。我想也认为日志文件也带有时间戳,因此您可以知道“从今天开始”处理行,或者您想要的任何日期范围。

答案 1 :(得分:1)

您是否无法使用访问此数据库的现有代码并根据您的需求进行调整?当然,代码必须是可怕的,但可能为您处理数据库结构,不是吗?你可以集中精力完成你的工作,而不是去考古学家。

答案 2 :(得分:1)

日志文件(二进制日志)也是我的第一个想法。如果你知道他们是怎么做的,你会不寒而栗。对于每一行,在添加和更改片段时,日志中有许多条目。它只是巨大的! 现在我决定使用Hash方法。通过一些聪明的文件内存分页,这非常快。

答案 3 :(得分:0)

您可以使用maatkit的mk-table-sync工具来同步登台数据库(毕竟你的数据库非常小)。这将“复制混乱”

然后,您可以编写一些内容,在同步之后执行各种查询以生成一组更理智的表格,然后您可以报告这些表格。

我想这可以在没有性能问题的情况下每天完成。

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

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