在数据库中删除数据的成本是,很高昂的,而且不安全的
真正执行删除操作,往往会导致 数据库 此表中 被删除数据 之后的 数据的 大量迁移,甚至再删除操作 过于频繁时,索引都有重新建立可能。 如果发生了这样的情况,说明此时的 业务已经足够繁忙, 再次引发数据库本身的数据迁移索引重建,无疑是雪上加霜 而且万一发生了错误删除,补救措施 也会变得十分困难,不凭借专业手段 去扫描磁盘,恢复数据,基本不可能做到。 这些情况在 cinder是如何处理呢?
cinder 中 数据库表 设计的优点
为了解决删除 瓶颈,cinder采用了 每张表 都加上 deleted 字段,即可 然后由于每张表 都需要 这个字段 以及 id 字段,以及 更新时间字段, 删除时间字段,创建时间字段 所以 cinder 直接写了一个 表映射对象 父类,让其他所有 表映射对象 去继承 名称叫做: CinderPersistentObject
字段定义内容
class CinderPersistentObject(object):
"""Mixin class for Persistent objects.
This adds the fields that we use in common for all persistent objects.
"""
fields = {
'created_at': fields.DateTimeField(nullable=True),
'updated_at': fields.DateTimeField(nullable=True),
'deleted_at': fields.DateTimeField(nullable=True),
'deleted': fields.BooleanField(default=False,
nullable=True),
}
@contextlib.contextmanager
def obj_as_admin(self):
"""Context manager to make an object call as an admin.
This temporarily modifies the context embedded in an object to
be elevated() and restores it after the call completes. Example
usage:
with obj.obj_as_admin():
obj.save()
"""
if self._context is None:
raise exception.OrphanedObjectError(method='obj_as_admin',
objtype=self.obj_name())
original_context = self._context
self._context = self._context.elevated()
try:
yield
finally:
self._context = original_context
总结
现在存储成本降低很快,昂贵的反而是数据,所以慎用 drop 删除指令。 当数据是在很多的时候,也应该去思考编写 一个 定时压缩 数据库导出数据的脚本之后,再考虑删除数据。 也可以考虑对 /var/lib/mysql 中的数据库存储文件 本身压缩后,进行留存。