我在编码时决定为每种类型的内容提供不同的表格。现在我无法解决这个问题。基本上我的通知系统按当前时间戳排列最新内容。这是不准确的,因为有人很可能会与另一个人同时提交内容,并且会出现错误的排名。
现在,如果我将所有内容都放在一个表中,我只需将其按自动递增变量进行排名即可。有没有办法在多个表中实现这个自动增量整数(例如,当某些内容插入到 table1 中时,id = 0,某些内容被插入 table2 ,id = 1 )。或者我必须将所有内容重新编码到一个表中。
注意:
我在多个表中有内容的原因是因为它有条理并且它会减少负载压力。我不再关心组织,因为我可以通过我编码的GUI访问数据,我只是想知道负载压力。
修改
我正在使用PHP 5和MySQL。
答案 0 :(得分:4)
您的问题,特别是跨越多个表的ID需求,显然表明您的数据库设计需要改变。您应该为所有内容类型创建一个表(作为一般化),并使用自动增量ID。然后,对于每种特定的内容类型,您可以使用额外字段定义其他表(相当于OOP中的继承),并将外键指向基本表。
换句话说,你需要像inheritance in SQL这样的东西。
答案 1 :(得分:2)
在单个表格中,您可以为包含content type
字段的clustered
和content type
索引添加字段。这有效地将所有一种内容类型保存在光盘上的一个位置,将另一种内容类型保存在另一个地方等等(它实际上组织成页面,但这种物理组织仍然是真实的。)
假设每个内容类型具有相同的字段,这可能会满足您的需求和的行为与多个表类似。在某些情况下,您甚至可能会发现,使用适当的索引,单个表解决方案可以更快,更方便和可维护等。例如尝试在所有内容类型中创建全局唯一标识符。
如果您无法将这些合并回单个表格中,可以创建中央链接表...
CREATE TABLE content_link (
id INT IDENTITY(1,1), -- MS SQL SERVER syntax
content_type INT,
content_id INT -- The id from the real table
)
在插入内容表时,还要插入链接表以创建全局唯一ID。
更简单,但更手动,只需在数据库中的某个位置保留一个值即可。每当您需要新的id时,请使用该集中存储的值并将其递增1。务必将增量和集合包装在单个事务中以停止竞争条件。 (这可以通过多种方式完成,具体取决于您的SQL风格。)
修改强>
来自网络的几个MySQL示例代码行......
START TRANSACTION;
INSERT INTO foo (auto,text)
VALUES(NULL,'text'); # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
VALUES(LAST_INSERT_ID(),'text'); # use ID in second table
COMMIT TRANSACTION;
就个人而言,我实际上将值存储在变量中,提交事务,然后继续我的业务逻辑。这将使表上的锁保持最小。
答案 2 :(得分:1)
您可以创建一个自动增量ID为的表,以便跟踪ID。你的程序会在该表上插入,获取id,必要时使用它。
有些事情:
function getNextId() {
$res = mysql_query("INSERT INTO seq_table(id) VALUES (NULL)");
$id = mysql_insert_id();
if ($id % 10 == 0) {
mysql_query("DELETE FROM seq_table");
}
return $id;
}
其中seq_table是您为了获取ID而创建的表。使其成为一种功能,以便您可以随时使用。生成的每10个ID我删除所有生成的ID,无论如何你不需要它们。我不会每次都删除,因为它会减慢。如果在此期间发生了另一个插入,并且我删除了11个或更多记录,则不会影响此过程的行为。它必须达到目的是安全的。
即使表是空的,新的ID也会继续增长,因为你已经将id声明为自动增量。
更新:我想澄清为什么ID生成没有包含在事务中以及为什么不应该包含它。
如果生成自动ID并回滚交易,则下一个自动ID将会增加。摘录自MySQL bug report:
[...]这不是一个bug,而是我们所知道的每个RDBMS中发生的预期行为。生成的值不是事务的一部分,也不关心其他语句。
使用此过程获取ID完全是线程安全的。获取ID后的逻辑应该包含在事务中,尤其是在处理多个表时。
以这种方式获取序列并不是一个新概念,例如,作为稳定数据库访问库的metabase_mysql.php代码有一个名为GetSequenceNextValue()的方法,它非常相似。
答案 3 :(得分:1)
您可以拥有一个单独的ID表,插入其中,然后使用新插入的ID。
e.g。
CREATE TABLE ids (INT UNSIGNED AUTO INCREMENT PRIMARY KEY, timeadded DATETIME);
在剧本中:
<?php
$r = mysql_query('INSERT INTO ids (timeadded) VALUES (NOW())');
$id = mysql_insert_id();
mysql_query("INSERT INTO someOtherTable (id, data) VALUES ('$id', '$data)");
添加错误检查等。
MySQL手册说明:
生成的ID在服务器上维护 每个连接基础。这意味着返回的值 给定客户端的函数是生成的第一个AUTO_INCREMENT值 对于影响AUTO_INCREMENT列的最新语句 客户。此值不受其他客户端的影响,即使它们也是如此 生成自己的AUTO_INCREMENT值。此行为可确保 每个客户端都可以检索自己的ID而无需担心 其他客户的活动,无需锁或 交易。
(Source)所以我不认为对ACID complians的担忧是一个问题。