构建管理员批准系统的最佳实践

时间:2017-05-29 08:36:27

标签: mysql database-design admin change-management

应该有一个管理面板的子系统,不同的用户可以管理他们的产品,但每个更改都应该在影响主产品表之前由管理员批准。 主要有三个表:

  1. 产品:存储已经最终批准并在整个系统中使用的产品
  2. Changes_versions:与产品表具有一对多关系的表,表示每个更改版本由管理员批准/拒绝的人,何时,何时提交或仍处于挂起状态。表结构如下:

    CREATE TABLE `changes_versions` (
      `xid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `xcreated_date` datetime DEFAULT NULL,
      `xupdated_date` timestamp NULL DEFAULT NULL,
      `xversion` int(11) DEFAULT NULL,
      `xobject_id` int(11) DEFAULT NULL,
      `xobject_type` varchar(255) DEFAULT NULL,
      `xstate` enum('PENDING','ACCEPTED','REJECTED') DEFAULT 'PENDING',
      PRIMARY KEY (`xid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=165 DEFAULT CHARSET=utf8
    
  3. 更改:与Changes_versions表具有一对多关系的表,保留主表的每个列更改记录(此处为我的意思是产品表),并通过管理员批准change_version记录,其相关更改记录将是放在主表列中。表结构如下:

    CREATE TABLE `changes` (
      `xid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `xcreated_date` datetime DEFAULT NULL,
      `xcreated_by` varchar(255) DEFAULT NULL,
      `xupdated_date` timestamp NULL DEFAULT NULL,
      `xupdated_by` varchar(255) DEFAULT NULL,
      `xversion_id` int(11) DEFAULT NULL,
      `xcolumn_name` varchar(255) DEFAULT NULL,
      `xcolumn_value` varchar(255) DEFAULT NULL,
      `xstate` enum('PENDING','ACCEPTED','REJECTED') DEFAULT 'PENDING',
      `xadmin_review` text,
      PRIMARY KEY (`xid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=764 DEFAULT CHARSET=utf8
    
  4. 使用此系统和表模式处理以处理记录更改,用户获取记录列表,如果用户有任何待处理状态change_version,系统将提取其相关更改记录并将它们放在提取的产品行的右列中(暂时只是用于显示),所以即使用户有任何待处理状态更改,他/她也可以在他/他的面板(不是主系统,只有他/她的面板)中看到它的变化。

    问题是插入新记录,我可以创建一个change_version记录,并将所有用户数据保存到指向新的change_vesrion记录的更改表,但是由于没有记录,change_vesrsion记录没有连接到任何产品记录。

    请注意,根据系统复杂性和当前稳定性,我不想在产品表中添加任何列来表明这是一个临时记录。

    所以我想要一个策略来处理问题,例如当我在用户面板中对产品进行分页并用最后的PENDING更改填充它们时,没有插入记录的产品记录来填充更改,因此用户无法看到他/她之前插入的产品。

    我还应该注意到这个表结构可能看起来很复杂。这个结构很复杂,因为changes_vesrsion和chaneges table为许多具有不同结构的表保存并呈现历史和管理批准过程。

3 个答案:

答案 0 :(得分:2)

让我先用我的话来描述你的问题(如果我错了,请纠正我。)

系统中有不同的项目(如产品),每个项目类型有一个(InnoDB)表格。 每个项目表都有一个AUTO_INCREMENT列(如id)。 您有一个项目版本表(changes_versions)来存储特定项目的不同版本。 该项目由列

标识
  • xobject_type(例如' product')引用了一个表
  • xobject_id这是一个"多态外键"引用上表中的PK

问题:当用户创建新项目时,不应将其插入项目表中, 但您需要在xobject_id列中存储引用。

可能的解决方案:"预留"通过在事务中插入和删除行来获取ID。

示例:

start transaction;
insert into products(column_1, column_2) values ('value_1', 'value_2');
delete from products where id = last_insert_id();
select last_insert_id();
commit;

你会得到什么:

  • 其他用户永远不会看到插入的行,因为它在同一事务中被删除。
  • last_insert_id()仍将从已删除的行中返回自动生成的ID;
  • 该ID将被烧毁",因此引擎永远不会再生成它。
  • 当管理员接受该项目时,您仍然可以手动插入该ID。
  • 不需要更改数据库架构。

演示:http://rextester.com/IJB42705

答案 1 :(得分:2)

解决方法是创建所有表格,当用户在changes_version表格中创建产品时,应该有一个 mysql事件,定期检查product中的每个记录表并将其与changes_version表匹配。如果在changed_version表中找到任何更改或新插入,则应相应地插入/更新product表。

修订解决方案:

您可以通过在用户登录时将用户记录从changes_version插入产品表并在注销时将其删除来实现。这适用于那些尚未移入product表的产品,您可以通过查询进行检查。

如果您有前端源,那么您只能向用户显示changes_version记录,并在获得批准后通过触发器将其移至product表。

答案 2 :(得分:1)

我认为SQL View在这里很方便,更改您的表名并添加一个标志字段,该字段由该字段标记临时行,然后创建一个名为Product的视图,并在视图中排除此字段和此字段标记的行通过这种方式,您的原始表(现在转换为视图)将保持未触及