【问题标题】:Schema migration on GAE datastoreGAE 数据存储上的架构迁移
【发布时间】:2011-07-05 10:57:45
【问题描述】:

首先,这是我在 Stack Overflow 上的第一篇文章,所以请原谅任何新手的错误步骤。如果我能更清楚地说明我的问题是如何提出的,请告诉我。

我正在 Google App Engine 上运行一个大型应用程序,并且一直在添加新功能,这些功能迫使我修改旧数据类并添加新数据类。为了清理我们的数据库并更新旧条目,我一直在尝试编写一个脚本,它可以遍历类的实例,进行更改,然后重新保存它们。问题是当您调用服务器的时间超过几秒时,Google App Engine 会超时。

我已经为这个问题苦苦挣扎了好几个星期。我找到的最佳解决方案在这里:http://code.google.com/p/rietveld/source/browse/trunk/update_entities.py?spec=svn427&r=427

我为自己的网站创建了该代码的一个版本,您可以在此处查看:

def schema_migration (self, target, batch_size=1000):
    last_key = None
    calls = {"Affiliate": Affiliate, "IPN": IPN, "Mail": Mail, "Payment": Payment, "Promotion": Promotion}

    while True:
        q = calls[target].all()
        if last_key:
            q.filter('__key__ >', last_key)
        q.order('__key__')
        this_batch_size = batch_size

        while True:
            try:
                batch = q.fetch(this_batch_size)
                break
            except (db.Timeout, DeadlineExceededError):
                logging.warn("Query timed out, retrying")
                if this_batch_size == 1:
                    logging.critical("Unable to update entities, aborting")
                    return
                this_batch_size //= 2

        if not batch:
            break

        keys = None
        while not keys:
            try:
                keys = db.put(batch)
            except db.Timeout:
                logging.warn("Put timed out, retrying")

        last_key = keys[-1]
        print "Updated %d records" % (len(keys),)

奇怪的是,该代码非常适合具有 100 到 1,000 个实例的类,并且脚本通常需要大约 10 秒。但是当我尝试在我们的数据库中运行具有更多类似 100K 实例的类的代码时,脚本运行了 30 秒,然后我收到了这个:

“错误:服务器错误

服务器遇到错误,无法完成您的请求。 如果问题仍然存在,请报告您的问题并提及此错误消息和导致它的查询。""

知道为什么 GAE 会在 30 秒后超时吗?我可以做些什么来解决这个问题?

谢谢! 凯勒

【问题讨论】:

  • 你真的应该早点问这个问题。可以在这里,也可以在 App Engine Google Group (groups.google.com/group/google-appengine-python) 上。迁移是一个常见问题,人们可以提供很多解决方案。不要孤军奋战。

标签: python google-app-engine migration schema google-cloud-datastore


【解决方案1】:

您的解决方案将从迁移到使用 GAE 的任务队列开始。此功能将允许您将更多工作排队等待稍后发生。

这实际上并不能立即解决问题,因为即使任务队列也仅限于短时间片。但是,您可以展开循环以一次处理数据库中的少量行。完成每个批次后,它可以检查它已经运行了多长时间,如果已经足够长,它可以在队列中启动一个新任务,以继续当前任务将停止的位置。

另一种解决方案是迁移数据。更改实现逻辑,以便每个实体都知道它是否已迁移。新创建的实体或更新的旧实体将采用新格式。由于 GAE 不要求实体具有所有相同的字段,因此您可以轻松地做到这一点,而在关系数据库中这是不切实际的。

【讨论】:

  • 任务队列现在可以运行 10 分钟。由于他们可以在 10 秒内完成 1000,因此他们可能能够在 10 分钟内运行整个迁移。
  • 感谢 Ozone 和 MacGuy 的帮助!我真的很感谢你花时间引导我朝着正确的方向前进。现在正在处理任务队列 API...
【解决方案2】:

您听到第二个 DeadlineExceededError 的声音。 AppEngine 请求每个只能运行 30 秒。当 DeadLineExceedError 引发时,您的工作是停止处理并在时间不多时进行整理,下次引发它时您将无法捕捉到它。

您应该考虑使用Mapper API 将您的迁移分成多个批次并使用任务队列运行每个批次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-10
    • 2012-06-09
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多