【问题标题】:Capturing Entity State Transactions捕获实体状态事务
【发布时间】:2017-07-20 04:39:44
【问题描述】:

我有一个与我的运行 php 和 mysql 的 API 通信的应用程序。 我想要做的是记录每个用户在我的表中的实体发生的变化。如果用户更改了他们的数据,我可以看到发生的更改。这样,如果他们有问题或不小心删除了某些内容,我可以回去告诉他们实体在一年中不同阶段的样子。

我不需要对差异非常具体,我想做的只是记录插入或更新(因为它在 JSON 正文中表示)。

基本上我现在所做的就是每当我的 API 针对某些路由发生 POST/PUT 时,我只需将 JSON 放入请求正文中,并将其作为发生的事务保存到数据库中的记录中为该用户。

这在早期很棒,但是在数十万条记录之后,JSON 主体很大并且占用了大量空间。我的数据库表是 13GB。查询也需要一段时间才能运行。我截断了它,但在 4 个月内它又增长到了 10GB。这个问题可能只会变得更大。

有没有人可以推荐的方法来记录这个?我可以将请求正文发送到 AWS 上的某个东西或其他一些离线存储或其他地方的另一个数据库吗?也许是平面文件或非关系数据库?这并不是说我真的需要实时数据,但如果我想获得某人的历史,我想知道我可以。

我确实每晚对数据库进行备份,因此另一种方法是我正在考虑完全删除事务日志,而只是让它继续每晚备份。当然,我将无法显示更新/添加实体的日期的历史记录,但至少我总是可以参考一些备份来查看在我进行还原后特定日期给定用户的记录。

有什么想法或建议吗?谢谢!

【问题讨论】:

    标签: php mysql backup api-design database-backups


    【解决方案1】:

    除了记录整个 JSON,您可以只记录已更改的值,也不必记录插入数据,因为您的数据库将始终具有当前记录,而记录插入数据是多余的。

    您可以实现 Diff 函数来比较现有 JSON 与更改后的 JSON 的差异。

    为了说明示例,请参见下面的代码,该代码从 Answer 借用了 JavaScript Diff 函数。

    // get the current value from your database
    var oldvalues = {
      "id": 50,
      "name": "Old Name",
      "description": "Description",
      "tasks": [{
        'foo': 'bar'
      }]
    };
    var newvalues = {
      "id": 50,
      "name": "New name",
      "description": "Description",
      "tasks": [{
        'foo': 'bar'
      }]
    };
    
    var isEmptyObject = function(obj) {
                        var name;
                        for (name in obj) {
                            return false;
                        }
                        return true;
                    };
    
    
     var diff = function(obj1, obj2) {
                        var result = {};
                        var change;
                        for (var key in obj1) {
                            if (typeof obj2[key] == 'object' && typeof obj1[key] == 'object') {
                                change = diff(obj1[key], obj2[key]);
                                if (isEmptyObject(change) === false) {
                                    result[key] = change;
                                }
                            }
                            else if (obj2[key] != obj1[key]) {
                                result[key] = obj2[key];
                            }
                        }
                        return result;
                    };
    
    var update = diff(oldvalues, newvalues);
    //save this to your database
    
    $('#diff').text(JSON.stringify(update));
    textarea {
      width: 400px;
      height: 50px
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    
    <textarea id="diff"></textarea>

    如您所见,唯一要保存的更改是 {"name":"New name"},这将减少您的数据使用量。

    您当然需要移植这个 PHP 或查看一些现有的包,例如 node-rus-diff 可能满足您的需求。

    只要您保留时间戳或序列号,您就可以链接多个事务以回滚到任何先前的状态。这类似于进行增量备份。

    如果您想创建检查点并将当前状态与之前的状态进行比较,您还可以按设定的时间间隔运行维护任务。也许每月一次备份并记录已更改对象之间的差异。这类似于差异备份。

    最后,您可以进行完整备份并清除以前的事务,类似于完整备份。

    管理员通常会执行增量备份、差异备份和完整备份的组合来平衡存储成本和恢复需求。使用上面概述的这些方法,您可以实施适合您的策略。

    【讨论】:

    • 感谢您花时间阅读我的帖子。 90% 的请求实际上是 POSTS(新实体),抱歉我没有提到这一点。在这种情况下,您对方法有其他想法吗?谢谢亚历克斯
    • 是的,当然,您不需要审核插入。这是多余的。您的数据库已经具有新记录的属性,无需在日志中复制副本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    相关资源
    最近更新 更多