gpt4 book ai didi

python-3.x - 是否可以在 EFS 中可靠地使用 SQLite?

转载 作者:行者123 更新时间:2023-12-05 04:35:24 24 4
gpt4 key购买 nike

是否可以在 AWS EFS 中安全地使用 SQLite?在我试图确定这是否可行的阅读 Material 中,似乎有一些暗示它应该可行,因为 AWS EFS 在 2017 年实现了 NFSv4。实际上,我没有运气从中获得一致的行为。

快点:

  1. “只需使用 AWS RDS”:由于其他 AWS 架构存在问题,另一个团队已实现我们正在尝试解决由 API 导致的资源匮乏问题(DynamoDB 不是一个选项)
  2. “这与 SQLite 的主要用例(作为本地访问数据库)背道而驰:是的,但考虑到这种情况,这似乎是最好的方法。
  3. 我已验证我们正在 EC2 实例上运行 nfsv4

无论我使用何种方法,当前结果都与遇到的 3 个异常非常不一致

  1. “文件已加密或不是数据库”
  2. “磁盘 I/O 错误(可能与 EFS 打开文件限制有关)”
  3. “database disk image is malformed”(此后数据库实际上并没有损坏)

数据库代码:

SQLITE_VAR_LIMIT = 999
dgm_db_file_name = ''
db = SqliteExtDatabase(None)
lock_file = f'{os.getenv("efs_path", "tmp")}/db_lock_file.lock'


def lock_db_file():
with open(lock_file, 'w+') as lock:
limit = 900
while limit:
try:
fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
print(f'db locked')
break
except Exception as e:
print(f'Exception: {str(e)}')
limit -= 1
time.sleep(1)

if not limit:
raise ValueError(f'Timed out after 900 seconds while waiting for database lock.')


def unlock_db_file():
with open(lock_file, 'w+') as lock:
fcntl.flock(lock, fcntl.LOCK_UN)
print(f'db unlocked')


def initialize_db(db_file_path=dgm_db_file_name):
print(f'Initializing db ')
global db
db.init(db_file_path, pragmas={
'journal_mode': 'wal',
'cache_size': -1 * 64000, # 64MB
'foreign_keys': 1})
print(f'db initialized')


class Thing(Model):
name = CharField(primary_key=True)
etag = CharField()
last_modified = CharField()

class Meta:
database = db

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

@staticmethod
def insert_many(stuff):
data = [(k, v['ETag'], v['Last-Modified']) for k, v in stuff.items()]
fields = [Thing.name, Thing.etag, Thing.last_modified]
limit = 900
while True:
try:
with db.atomic():
for key_batch in chunked(data, SQLITE_VAR_LIMIT // len(fields)):
s = Thing.insert_many(key_batch, fields=[Thing.name, Thing.etag, Thing.last_modified]) \
.on_conflict_replace().execute()
break
except Exception as e:
print(f'Exception: {str(e)}')
print(f'Will try for {limit} more seconds.')
limit -= 1
time.sleep(1)

if not limit:
raise ValueError('Failed to exectue query after 900 seconds.')

调用示例:

        print(f'Critical section start')
# lock_db_file() # I have tried with a secondary lock file as well
self.stuff_db = Thing()
if not Path(self.db_file_path).exists():
initialize_db(self.db_file_path)
print('creating tables')
db.create_tables([Thing], safe=True)
else:
initialize_db(self.db_file_path)

getattr(Thing, insert_many)(self.stuff_db, stuff_db)
# db.close()
# unlock_db_file()
print(f'Critical section end')
print(f'len after update: {len(stuff)}')

其他特性:

  • 如果一个 lamda 卡住捕获“格式错误的图像”异常并触发新的 lambda 执行,则错误在另一个 lambda 中解决。

最佳答案

经过反复试验,我发现这是一个可行的解决方案。看来该设计需要使用 APSWDatabase(..., vfs='unix-excl') 来正确执行锁定。

数据库代码:

from peewee import *
from playhouse.apsw_ext import APSWDatabase

SQLITE_VAR_LIMIT = 999
db = APSWDatabase(None, vfs='unix-excl')


def initialize_db(db_file_path):
global db
db.init(db_file_path, pragmas={
'journal_mode': 'wal',
'cache_size': -1 * 64000})
db.create_tables([Thing], safe=True)

return Thing()


class Thing(Model):
field_1 = CharField(primary_key=True)
field_2 = CharField()
field_3 = CharField()

class Meta:
database = db

这允许以下用法:

        db_model = initialize_db(db_file_path)
with db:
# Do database queries here with the db_model
pass

注意:如果您不使用上下文管理的数据库连接,您将需要显式调用 db.close() 否则锁不会从文件中释放。此外,调用 db_init(...) 会在 databased 上放置一个锁,直到它关闭。

关于python-3.x - 是否可以在 EFS 中可靠地使用 SQLite?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71042228/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com