Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 数据库-单个表中的数据版本控制_Php_Database_Versioning - Fatal编程技术网

Php 数据库-单个表中的数据版本控制

Php 数据库-单个表中的数据版本控制,php,database,versioning,Php,Database,Versioning,我正在开发一个CMS,它有一些版本控制功能。它基于MySQL数据库 这样做的目的是向公众网站访问者展示数据的某个版本,并向后台用户展示最新版本的预览。发布某个内容只意味着将某个版本设置为最新版本,并可能删除旧版本的数据 我读过一些关于这个主题的问答,大多数都认为将旧行和新行放在同一个表中是不好的。但是,由于我需要连接表,所有表都有版本,在不同的表中拆分旧的和新的也不理想。应用程序如何知道一个版本中的内容是旧的还是新的,从而在历史记录表中找到还是不找到 所以我决定对每种内容类型只使用一个表 我使用

我正在开发一个CMS,它有一些版本控制功能。它基于MySQL数据库

这样做的目的是向公众网站访问者展示数据的某个版本,并向后台用户展示最新版本的预览。发布某个内容只意味着将某个版本设置为最新版本,并可能删除旧版本的数据

我读过一些关于这个主题的问答,大多数都认为将旧行和新行放在同一个表中是不好的。但是,由于我需要连接表,所有表都有版本,在不同的表中拆分旧的和新的也不理想。应用程序如何知道一个版本中的内容是旧的还是新的,从而在历史记录表中找到还是不找到

所以我决定对每种内容类型只使用一个表

我使用的设计: 每个表都包含一个主键的修订INT NOT NULL列部分以及一个ID列

修改某些内容意味着插入一个具有修改值的新行,一个增量修订,但ID相同

插入某物意味着插入一个ID递增且修订版本递增的新行

删除某些内容意味着插入一个具有相同ID、递增版本和设置为true的thumbstone标志的空行

示例:有些页面和视图视图不是MVC意义上的视图,而是应用程序特定意义上的视图。视图是版本化的。一个页面有许多视图。 这是观点的一部分

CREATE TABLE `_views` (
  `_id` int(11) NOT NULL,
  `_rev` int(11) NOT NULL,
  `_ts` BIT(1) DEFAULT b'0',
  `page` int(11) NOT NULL,
  `order` int(11) NOT NULL,
  PRIMARY KEY (`_id`,`_rev`)
)
我需要按照order指定的顺序选择页面包含的所有视图,直到某个版本

此查询可用于:

SELECT * FROM (
 SELECT *
 FROM `_views`
 WHERE `page` = :page
 AND `_rev` <= :revision
 ORDER BY `_rev` DESC
) AS `all`
GROUP BY `_id`
HAVING `_ts` = 0
ORDER BY `order`
子查询选择页面的所有视图,这些视图一旦发布,其版本小于或等于发布的版本。外部查询将这些组分组为其最新版本,删除具有缩略图的组,并按特定于应用程序的条件对其排序

既然CMS的可伸缩性和性能至关重要,难道没有比子查询更好、更优雅的方法吗


。。。或者我应该专注于缓存吗?

使用子查询来确定当前版本不是最好的方法;你真的不想去那里

一种更简单的方法是添加一个标志,告诉您最新版本:

   `_rev` int(11) NOT NULL,
   `_current` BIT(1),
这需要手动更新,以便在添加新版本或更改_ts标志时设置_current标志。但至少这样可以避免在每个页面显示上执行子查询

作为替代方案,您仍然可以将数据拆分为“当前”和“历史”表。然后,如果需要再次连接结果集,则只需在这两种情况下创建一个视图:

 CREATE VIEW pages_all AS
      SELECT * FROM pages_current
      UNION ALL SELECT * FROM pages_history

同样,如果您需要经常对所有活动的非缩略图修订进行分组,也可以创建所有活动的非缩略图修订的子表。尽管这比当前标志或历史表上的视图需要更多的人工微观管理。

拇指石的目的是什么?它是墓碑的另一种拼写。打个比方,这是一个标志,标志着某些东西被删除了。因此,通过删除此删除版本+1以存储当前版本,可以轻松恢复该版本。我认为这是最好的方法,创建一个ON INSERT触发器有助于使这个过程透明。当前标志的问题是:当前的内容取决于谁查看页面。管理员看到最后一个版本,普通访问者看到另一个当前版本。此外,管理员需要能够切换到他想要的任何修订版本,以便进行比较。我需要比较UNION ALL和子查询之间的性能命中率。@user913761:听起来这更像是应用程序编码问题。无论如何,您都需要为前端和后端动态调整SQL。因此,您可以查询两个不同的表集,或者只对前端使用_current标志。尽管我不确定自己是否完全掌握了使用修订分组的方法。你的情况似乎有点复杂联合所有人的观点可能仍有帮助;据我所知,它只是一个附加,甚至不涉及临时表;sql语句保持不变,我只是将另一个修订传递给:revision参数。但是,我可以为前端使用_current标志来定义current=published