【问题标题】:How to keep track of the files I read into a database in python?如何跟踪我在 python 中读入数据库的文件?
【发布时间】:2018-03-27 14:44:47
【问题描述】:

情况

我从远程数据源获得了大量的 json 文件。我将这些文件组织成一个档案,然后将它们读入数据库。如有必要,存在存档以重建数据库。

json 文件是远程生成的,并定期发送到我的服务器,并且读入过程不断发生。不止一次,我们的服务器在一夜之间或周末断电,这对于数据库加载来说是一个巨大的问题,因为进程停止了,我不知道什么已经加载,什么没有所以我必须回滚到某个先前已知的状态并从存档中重建。

为了解决这个问题,我的主加载器守护程序(用 python 编写)现在使用logging 包来跟踪它已加载的文件。 loader daemon 的基本工作流程是

  • cp要归档的json文件
  • `rm' 原创
  • 将存档副本插入数据库(其 MariaDB)
  • 提交到数据库
  • 加载的json文件的日志文件名

我不太担心数据库中的重复,但我不希望出现空白;也就是说,档案中的东西不在数据库中。到目前为止,这种方法似乎可以保证防止任何差距。

对于我的日志记录,它基本上看起来像这样。当守护程序在一组接收到的文件名上启动时,它会检查已经加载到目标数据库的重复文件,然后加载所有非重复文件。可以从我的远程数据源中获取重复项。

def initialize_logs(filenames, destination)
   try:
      with open("/data/dblogs/{0}.log".format(destination), 'r') as already_used:
         seen = set([line.rstrip("\n") for line in already_used])
   except FileNotFoundError:
      print("Log file for {0} not found. Repair database".format(destination))
      quit()

   fnamelog = logging.getLogger('filename.log')
   fnamelog.setLevel(logging.INFO)
   fh = logging.FileHandler("/data/dblogs/{0}.log".format(destination))
   fh.setLevel(logging.INFO)
   fnamelog.addHandler(fh)

然后,当我处理 jsonfiles 时,我会记录使用添加的每个文件

fnamelog.info(filename)

数据库加载器是并行运行的,所以我最初选择了logging 包,因为它内置了并发保护。有多种数据库;并非每个数据库都从 json 文件中提取所有数据。一些信息较多的数据库时间较短,一般为一到两个月。在这种情况下,在给定数据库中有一个包含所有 json 文件的日志文件是很好的,所以如果我想在上面添加一些,我不必担心那里已经存在什么,日志文件是跟踪。


问题

一年过去了。我一直在获取 json 文件。我现在每月收到大约一百万个文件。每个文件名在处理时的文本记录是笨拙的,但它仍然有效......现在。有多个数据库,但对于最大的数据库,日志文件超过半 GB。我觉得这个日志记录解决方案不会再好用了。

当每个数据库有超过 1000 万个文件名并且还在增加时,python 中有哪些选项可以跟踪哪些文件名已插入数据库?

【问题讨论】:

  • 您的文件名是否有顺序和唯一的名称?也许记住最后一个成功导入的文件的名称就足够了?
  • @Kos 它们具有唯一的名称并按时间戳排序。不幸的是,由于来自远程站点的连接问题,它们经常乱序到达;或者根本没有,它们必须手动移动。
  • 所以也许您还记得最后一个文件的属性,即该文件和该文件之前的所有文件都已成功导入且没有间隙?更新会有点棘手,但可能就足够了。

标签: python python-3.x logging mariadb


【解决方案1】:

一种方法是将文件记录在数据库本身的表中,而不是文本日志文件中。如果您为导入日期或文件名之类的内容添加了一些列,这可能会为您在需要时从这些日志中查找信息提供一点灵活性,而且它还允许您执行定期维护(例如例如删除超过几个月的日志记录,如果你知道你永远不需要查看这些记录)。

如果您决定继续使用基于文本的日志文件,您可能会考虑将它们拆分,这样您就不会得到一个庞大的单一日志文件。当您安装像 Apache 这样记录大量数据的东西时,您会看到它会自动设置 log rotation 以定期压缩和归档日志文件...

【讨论】:

    【解决方案2】:

    你没有说你使用的是什么类型的数据库,但一般采取的方法是

    1) 对每个 json 文件进行哈希处理。 SHA256 广泛可用。如果您担心性能,请参阅此帖子https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed

    2) 使哈希字段成为数据库上的唯一键,然后在执行其他操作之前尝试插入它。如果你不能记录已经存在并且交易将中止

    【讨论】:

    • 它是 MariaDB。问题中的某个部分的格式似乎不正确。
    • 我想了很多,独特的关键思想有一些优点。是否有任何理由使用每个 json 文件的哈希而不是仅在数据库中使用其文件名?我对这个系统没有任何安全问题。
    • 只要您绝对确定用于生成哈希的数据(文件名或整个文件)是唯一的,都可以
    【解决方案3】:

    方案一:

    Foreach file in input directory
        INSERT IGNORE into database the MD5 of the file
        "mv" the file to the archive directory
    

    程序 2,一个“保活”程序。

    它每分钟通过cron 运行并尝试启动程序 1,但如果它已经在运行,则不要启动它。

    注意事项:

    • 'mv' 和 'cron' 假定为 Unix。如果使用 Windows,请执行等效操作。
    • 'mv' 是原子的,因此文件将位于另一个目录中;毫不费力地知道它是否已“处理”。 (所以,我想知道为什么你还有一个数据库表??)
    • 由于INSERTmv 不能真正“原子地”完成,这就是为什么我的计划是安全的:IGNORE
    • “是否正在运行”可以通过多种方式处理,在程序 1 或 2 中。
    • 您可以在包含 md5 的表中添加时间戳和/或文件名;随心所欲。
    • 由于在一个目录中甚至有 10K 个文件都不是一个好主意,因此您应该使用我所设想的一对平面目录之外的其他东西。

    您每 3 秒只会获得大约 1 个文件。除非文件很大,否则这不是一个沉重的负担。然后就变成了 I/O 问题,而不是数据库问题。

    我有一种感觉,要么我错过了一个隐藏的“要求”,要么你变得更加偏执。我真的不明白你需要对这些文件做什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多