나는 모든 선택 사항을 거의 파악했다고 생각합니다.
- 데이터를 잃어 버리지 않도록 Google에 알리고 실수로 데이터를 삭제하도록하지 않았 으면합니다.
- 엄청나게 비싼 경우 밤에 한 번만 수행하는 것보다 덜 자주
download_data
으로 전체 백업을 수행하십시오.
- 증분 백업 솔루션을 롤백하십시오.
옵션 3은 실제로 흥미로운 아이디어입니다. 모든 엔티티에서 수정 타임 스탬프가 필요하고 삭제 된 엔티티를 잡아낼 수 없지만 remote_api 및 커서를 사용하면 매우 유용합니다.
편집 :
여기 remote_api 함께 사용할 수있는 간단한 증가 다운로더입니다. 다시 말하지만,주의해야 할 점은 삭제 된 엔티티를 인식하지 못하도록하며, 모든 엔티티가 updated_at라는 속성에 마지막 수정 시간을 저장한다고 가정합니다. 당신 자신의 위험에 그것을 사용하십시오.
import os
import hashlib
import gzip
from google.appengine.api import app_identity
from google.appengine.ext.db.metadata import Kind
from google.appengine.api.datastore import Query
from google.appengine.datastore.datastore_query import Cursor
INDEX = 'updated_at'
BATCH = 50
DEPTH = 3
path = ['backups', app_identity.get_application_id()]
for kind in Kind.all():
kind = kind.kind_name
if kind.startswith('__'):
continue
while True:
print 'Fetching %d %s entities' % (BATCH, kind)
path.extend([kind, 'cursor.txt'])
try:
cursor = open(os.path.join(*path)).read()
cursor = Cursor.from_websafe_string(cursor)
except IOError:
cursor = None
path.pop()
query = Query(kind, cursor=cursor)
query.Order(INDEX)
entities = query.Get(BATCH)
for entity in entities:
hash = hashlib.sha1(str(entity.key())).hexdigest()
for i in range(DEPTH):
path.append(hash[i])
try:
os.makedirs(os.path.join(*path))
except OSError:
pass
path.append('%s.xml.gz' % entity.key())
print 'Writing', os.path.join(*path)
file = gzip.open(os.path.join(*path), 'wb')
file.write(entity.ToXml())
file.close()
path = path[:-1-DEPTH]
if entities:
path.append('cursor.txt')
file = open(os.path.join(*path), 'w')
file.write(query.GetCursor().to_websafe_string())
file.close()
path.pop()
path.pop()
if len(entities) < BATCH:
break
마지막 질문에 [776] (http://code.google.com/p/googleappengine/issues/detail?id=776) –