15

これは、アプリケーションのログに毎日記録される一般的な例外であり、通常は 1 日あたり 1,000 回のアクセスのトラフィックで 1 日に 5/6 回発生します。

db error trying to store stats
Traceback (most recent call last):
  File "/base/data/home/apps/stackprinter/1b.347728306076327132/app/utility/worker.py", line 36, in deferred_store_print_statistics
    dbcounter.increment()
  File "/base/data/home/apps/stackprinter/1b.347728306076327132/app/db/counter.py", line 28, in increment
    db.run_in_transaction(txn)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 1981, in RunInTransaction
    DEFAULT_TRANSACTION_RETRIES, function, *args, **kwargs)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 2067, in RunInTransactionCustomRetries
    ok, result = _DoOneTry(new_connection, function, args, kwargs)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 2105, in _DoOneTry
    if new_connection.commit():
  File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1585, in commit
    return rpc.get_result()
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 530, in get_result
    return self.__get_result_hook(self)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1613, in __commit_hook
    raise _ToDatastoreError(err)
Timeout: The datastore operation timed out, or the data was temporarily unavailable.

上記の例外を発生させている関数は次のとおりです。

def store_printed_question(question_id, service, title):
    def _store_TX():
        entity = Question.get_by_key_name(key_names = '%s_%s' % \
                                         (question_id, service ) )
        if entity:
            entity.counter = entity.counter + 1                
            entity.put()
        else:
            Question(key_name = '%s_%s' % (question_id, service ),\ 
                          question_id ,\
                          service,\ 
                          title,\ 
                          counter = 1).put()
    db.run_in_transaction(_store_TX)

基本的に、このstore_printed_question関数は、特定の質問が以前に印刷されたかどうかをチェックし、その場合、単一のトランザクションで関連するカウンターをインクリメントします。
この関数は、定義済みのデフォルトWebHandlerキューを使用して遅延ワーカーに追加されます。ご存知のように、1 秒あたり 5 つのタスク呼び出しのスループット レートがあります。

6 つの属性 (2 つのインデックス) を持つエンティティでは、遅延タスクのレート制限によって規制されたトランザクションを使用 すると、データストアのタイムアウトを回避できると考えましたが、ログを確認すると、このエラーはまだ毎日表示されています。

私が保存しているこのカウンターはそれほど重要ではないので、これらのタイムアウトについて心配する必要はありません。とにかく、毎秒 5 タスクのような低いレートでも Google App Engine がこのタスクを適切に処理できない理由と、レートを下げることが可能な解決策であることに興味があります。
タイムアウトを回避するために各質問にシャード カウンターを配置するのは、私にとってやり過ぎです。

編集:
デフォルトのキューでレート制限を 1 秒あたり 1 タスクに設定しました。私はまだ同じエラーが発生しています。

4

2 に答える 2

9

クエリは30秒間しか存続できません。カーソルを使用してクエリを分割するためのサンプルコードについては、この質問に対する私の回答を参照してください。

于 2012-08-02T23:36:27.967 に答える
7

一般的に言えば、このようなタイムアウトは通常、書き込み競合が原因です。トランザクションが進行中で、同じエンティティ グループに同時に大量のデータを書き込んでいる場合、書き込みの競合の問題が発生します (オプティミスティックコンカレンシーの副作用)。ほとんどの場合、エンティティ グループを小さくすると、通常、この問題は最小限に抑えられます。

あなたの特定のケースでは、上記のコードに基づいて、シリアル化された書き込みのスタックを避けるためにシャード カウンターを使用する必要があるためと考えられます。

もう 1 つの可能性としてははるかに低い可能性があります (完全を期すためにここに記載されています) は、データが保存されているタブレットが移動されていることです。

于 2011-01-20T10:13:57.087 に答える