现在我使用remote_api和appcfg.py download_data
每晚拍摄我的数据库的快照。这需要很长时间(6小时)并且很昂贵。没有滚动我自己的基于变更的备份(我太害怕做类似的事情),什么是确保我的数据安全无故障的最佳选择?
答案 0 :(得分:3)
我认为你已经确定了所有的选择。
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