【问题标题】:One database, multiple customers一个数据库,多个客户
【发布时间】:2011-03-07 22:11:03
【问题描述】:

我目前正在编写一种产品,该产品只有一个数据库,但将使用 customer_id 的全局标识符托管许多客户端。

这一切都很好。

但是,假设我们有一个名为 Ticket 的表。 Idea 有一个主键。当用户添加工单时,工单将通过外键等方式与客户对应。

但是,对于每个客户,我希望他们的票证 ID 在他们注册时从 1 开始。

即客户 1 添加 4 张门票,ticket_id 计数将为 4。客户 2 注册,他们添加门票,然后 ticket_id 将为 5,依此类推。这并不理想。

我的问题是,如果我不想使用多个数据库,该如何解决?如果每当我进行更改时,数百个带有新列、索引等的数据库都会让我非常恼火,那么必须更新的想法往往会让我非常恼火。

希望这是有道理的,我期待您的意见。

编辑:标记为 symfony,因为我将在 symfony 中使用 Doctrine ORM 来管理数据库....可能无关紧要,但以防万一。

编辑:我可能也很愚蠢并且在这里遗漏了一些明显的东西,所以我很抱歉。

【问题讨论】:

  • 有些东西对我来说似乎有点不清楚。当您说“客户 2 注册时,他们添加了一张票,然后 customer_id 将为 5,依此类推”,您的意思是 ticket_id 将为 5 吗?我认为为每个客户增加ticket_id 效果很好。您必须支持的项目要少得多。如果您想创建 customer_id 和 ticket_id 的组合键,您可以在其中获取 ticket_id 的最大值,其中 customer_id 是另一个客户的 FK。但是,我认为让ticket_id 无视客户的增加是最好的主意
  • 抱歉,我意识到我犯了那个错误,并且已经更正了(实际上,是说ticket_id)。同意,只有ticket_id 会更简单、更容易,但是,我不希望客户认为“嗯?我的票号 4341 怎么样?我只创建了 2 张票?!”或者你认为这不是什么大问题?此外,我对其他公司如何使用诸如此类的集中式数据库并设法保持每个客户的连续 ID 等很感兴趣。
  • 这应该不是什么大问题,或者您是否查看了 SO 的 id 并认为“这个问题 3112050 是我自己在 php 中,一般来说,......”;)。如果你真的想移动 ID,你总是可以创建“漂亮的 URL”来隐藏 ID 并将其替换为票的标题或任何其他内容。
  • 除非用户想通过工单 id 进行搜索。呵呵,真麻烦!但你是对的,我会使用漂亮的网址。门票标题和时间戳(如建议)有点像 example.com/ticket/some-crazy-ticket-please-look-at-me-11545454
  • 如果你使用的是学说,那么你应该使用这个标签而不是 symfony

标签: php mysql database database-design doctrine


【解决方案1】:

为什么不只添加一个 ticket_num 列,并自己管理保持它们按客户 ID 顺序排列?如果您使用的是原则,请考虑在您的 Ticket 模型中实现 preInsert 方法。

【讨论】:

  • 因为如果我删除一张票,那么顺序就会被搞砸。 :-( 除非我使用软删除...
  • @Jamie -- 你为什么要删除一张票?只需关闭它,将其标记为已取代等。无论您如何计算 id,都会存在如何保持数字同步的问题。
  • 我当然会在票证之类的东西上使用 softdelete,要么使用原则行为,要么只是为票证实现一些“已删除”状态。
  • @MJB - 是的,这是真的。票只是一个例子,我也可以用用户作为例子。即客户 1 的用户 ID 1 和客户 2 的用户 ID 1。我可能会从系统中删除一个用户。也许我应该停止担心最终用户会在 url 等中看到什么。
【解决方案2】:

我是否理解每个客户的门票将从 1 开始按顺序列出?我将假设每个客户都有自己的票证,并且这些票证不会暴露给其他客户。你应该在你的问题中澄清这一点。

我建议在您的票证表中创建一个新列以用作参考号(我们称之为 ref_num)。当客户端 2 创建票证时,ticket_id 将为 5,但您的应用程序将知道为该用户分配 ref_num 为 1。

为了那个正常工作,您需要找到一种方法来跟踪每个客户创建的票证数量。也许对于每个联系人,您都可以有一个名为 ticket_count 的列,该列每次​​递增一。这样,在您的应用程序中,您只需提取此号码并将其加一即可更新您的计数并获取新的票号。

仅供参考,在这里我们不担心向用户隐藏信息。我们使用 ref_num 字段向用户隐藏真实的 ID 号。我们有多个部门,每个部门都有多个客户,共享同一个 ID 池。如果 A 组创建票证 23456,然后 B 组创建另一个票证,它显示为 23457,尽管之前的票证不属于他们。票号不需要连续。

【讨论】:

  • 你说得对,“每个客户都有自己的票,这些票不会暴露给其他客户。”你的想法似乎很可行,但有一个问题。如果由于某种原因数据库中出现故障并且我得到一个奇怪的票号计数,然后将其添加到票号 ref_num 中,我将陷入困境。只考虑最坏的情况。
  • 在将行插入数据库之前,您可以使用查询来计算该用户的现有票数,然后将该值加一,而不是存储票数。这是对 DB 的附加查询...尽管根据应用程序的大小、使用频率和用户数量,它可能并不重要。
  • 不计算,取最大值和增量。 SELECT MAX(ref_num) FROM tickets WHERE client_id=? 虽然如果门票永远不会被销毁,这应该是等效的,但您最好使用 MAX() 来确保您永远不会重复。
【解决方案3】:

另一种可能性是不使用连续整数票证 ID。你可以给票加上时间戳,甚至可以精确到秒,然后使用它。与我合作的某些供应商也会这样做。其他人会跟踪计数并将其附加到时间戳,这看起来像是一个没有间隙的唯一数字,但实际上可能不会以这种方式实现。

在这种情况下,客户看到像2010062407 这样的票号并认为,“显然这与日期有关,甚至可能与时间有关”。但我不认为客户会说,“我是如何获得 20 亿张故障单的?!”

【讨论】:

    【解决方案4】:

    在我看来,您混淆了主键和业务键的概念。主键的作用是唯一标识表中的一行,仅此而已。每当有人试图为主键附加意义时——最初的设计就有问题。

    如果票号具有某种商业意义——以及预期的顺序——只需为您的每个客户创建一个序列生成器并为此添加一列。

    【讨论】:

      【解决方案5】:

      创建一个名为 CustomerTickets 的新表,其中包含两列客户 ID 和工单 ID。 对于您的客户,从表中读取您的客户 ID 的最后一个工单 ID,将其递增,然后将其写入您的实际工单表中,所有这些都在事务中汇总。

      【讨论】:

        【解决方案6】:

        我会说你应该保持主 ID 保持原样,从逻辑上讲它应该是内部的。您可以生成唯一标识符(GUID、时间戳)并将其用于显示目的。或者,您可以生成一个唯一的 ID(用于显示目的),首先将 4 个客户姓名的字母组合起来,然后用 0 填充它。

        类似:

        APPL000006

        GOOG000004

        使用它,修剪前四个字母,然后你会得到你的主 ID。

        【讨论】:

          【解决方案7】:

          您还可以尝试为每个客户创建额外的表格,这样您最终会为每个客户创建新表格。
          例如。表格:

          tickets_1 //all tickets for customer with id 1
          tickets_3 //all tickets for customer with id 3
          

          (如果您没有成千上万的客户,这应该不是问题。)

          【讨论】:

          • 这听起来有问题。您是否还需要为每个客户为其他每张桌子提供一个新版本?所以 10 个客户意味着 10 个票据表、10 个订单表、10 个 rma 表等?在这种情况下,为什么不为每个客户提供一个单独的数据库或架构?
          • 同意 MJB,如果你是这个数据库的管理员,我不想切换 ;)
          • 因为:引用问题:“我目前正在编写一种产品,该产品只有一个数据库,但会承载许多客户”。这不像多个数据库那么容易,但它是可能的。
          猜你喜欢
          • 1970-01-01
          • 2023-03-09
          • 1970-01-01
          • 2015-05-09
          • 2011-02-17
          • 1970-01-01
          • 1970-01-01
          • 2017-05-03
          • 1970-01-01
          相关资源
          最近更新 更多