MySQL遗留数据库的终极噩梦
表格1:
一切都包括厨房水槽。日期格式错误(最后一年,因此我们无法在该列上排序),数字存储为VARCHAR,"街道"列中的完整地址,名字列中的名字和姓氏,姓氏列中的城市,不完整的地址,通过根据多年来更改过的一组规则,重复记录,不完整记录,垃圾记录等将一组数据从一个字段移动到另一个字段来更新先前的行...命名它……哦,当然不是TIMESTAMP或者PRIMARY可见KEY列。
表2:
在打开这个婴儿的门上,任何标准化的希望都荡然无存。
我们为每个条目都有一行,并在表一中更新了行。因此,像没有明天的副本(价值800MB)和像Phone1 Phone2 Phone3 Phone4 ... Phone15这样的列(它们不称为phone。我用它来举例说明)。根据表1中的行中的数据类型,有3个候选对象
表3:
它会变得更糟吗?哦是的。
"外键是由破折号,点,数字和字母组成的VARCHAR列组合!如果不提供匹配项(通常不提供),则应该使用相似产品代码的第二列。与它们中的数据没有关联,并且强制性的Phone1 Phone2 Phone3 Phone4 ... Phone15. 表1中有重复的列,而不是TIMESTAMP或者PRIMARY KEY列。
表4:被描述为一项进展中的工作,随时可能更改。这与其他类似。
在接近1m行的情况下,这真是一团糟。幸运的是,这不是我的大麻烦。不幸的是,我不得不为每个"客户"提取一份综合记录。
最初,我设计了Table1的四步转换,添加了PRIMARY KEY并将所有日期转换为可排序的格式。然后再执行几步查询,这些查询返回过滤后的数据,直到我拥有Table1为止,在那里我可以使用它从其他表中提取数据以形成复合文件。经过数周的工作,我使用了一些技巧将这一步骤简化为一步。因此,现在我可以将我的应用程序对准混乱局面,并提取出一个漂亮的干净的合成数据表。幸运的是,出于我的目的,我只需要一个电话号码,因此规范化我的表就不成问题了。
但是,这是真正的任务开始的地方,因为每天都有数百名员工以我们不想想象的方式添加/更新/删除该数据库,而且每天晚上我都必须检索新行。
由于任何表中的现有行都可以更改,并且由于没有TIMESTAMP ON UPDATE列,因此我将不得不求助于日志以了解发生了什么。当然,这假定存在二进制日志,而没有二进制日志!
引入概念的过程像铅球一样下降。我可能还告诉他们,他们的孩子将不得不进行实验性手术。他们并不是高科技,以防万一你没有聚集...
情况有些微妙,因为他们掌握了一些我公司急需的有价值的信息。我已经被一家大型公司的高级管理人员(我们知道他们是如何做到)所派来"实现"。
除了使用其他应用程序解析bin日志文件,弄清楚它们白天对数据库所做的工作,然后据此合成我的表,我想不出其他方法来处理夜间更新。我真的只需要查看他们的table1即可知道要对我的表执行什么操作。其他表仅提供用于刷新记录的字段。 (使用MASTER SLAVE将无济于事,因为我将得到一个混乱的副本。)
另一种方法是为其table1的每一行创建唯一的哈希,然后构建一个哈希表。然后,我每晚都要检查整个数据库,以检查哈希是否匹配。如果他们不这样做,那么我将读取该记录并检查它是否存在于数据库中,如果存在,那么我将在数据库中对其进行更新,如果不存在,则将其更新为新记录,然后将其插入。这很丑陋,而且速度不快,但是解析二进制日志文件也不是一件容易的事。
我写这是为了帮助弄清楚这个问题。通常将其告诉其他人有助于澄清问题,使解决方案更加明显。在这种情况下,我头疼更大!
想法将不胜感激。
解决方案
我们不能使用访问该数据库并使之适应需求的现有代码吗?当然,代码必须是可怕的,但是它可能会为我们处理数据库结构,不是吗?希望我们可以专注于完成工作,而不是那时去找考古学家。
我们也许可以使用maatkit的mk-table-sync工具同步登台数据库(毕竟,数据库很小)。这将"复制混乱"
然后,我们可以编写一些内容,在同步后执行各种查询,以生成一组更合理的表,然后可以进行报告。
我认为可以每天执行此操作而不会出现性能问题。
在不同的服务器上完成所有操作将避免影响原始数据库。
我能看到的唯一问题是某些表是否没有主键。
我不是MySQL使用者,所以这是左领域提出的。
但是我认为日志文件可能是答案。
值得庆幸的是,我们实际上只需要从日志中了解2件事。
我们需要记录/行,并且需要操作。
在大多数数据库中,我假设使用MySQL,每行上都有一个隐式列,例如rowid或者recordid或者其他。它是数据库使用的内部行号。这是"免费"主键。
接下来,我们需要操作。值得注意的是,它是对行的插入,更新还是删除操作。
我们可以按时间顺序合并所有这些信息,然后进行遍历。
对于每个插入/更新,请从原始数据库中选择该行,然后在目标数据库中插入/更新该行。如果是删除,则删除该行。
我们不在乎字段值,它们并不重要。做整行。
希望我们不必"解析"二进制日志文件,MySQL已经必须有例程来执行此操作,我们只需要查找并弄清楚如何使用它们(甚至可以使用一些方便的"转储日志"实用程序)。
这使我们可以使系统保持非常简单,并且仅应取决于白天的实际活动,而不是数据库的总大小。最后,我们可以稍后通过使其"更智能"来对其进行优化。例如,也许他们插入一行,然后对其进行更新,然后将其删除。我们会知道我们可以在重放中完全忽略该行。
显然,这需要一些奥术知识才能真正读取日志文件,但其余部分应该很简单。我想认为日志文件也带有时间戳,因此我们可以知道要处理"从今天开始"的行,或者要使用任何日期范围。
日志文件(二进制日志)也是我的第一个想法。如果我们知道他们是如何做的,我们就会发抖。对于每一行,随着片段的添加和更改,日志中有许多条目。它只是巨大的!
现在,我决定采用哈希方法。有了一些巧妙的文件内存分页,这是相当快的。