如何在 mysql 中的条件下增加行object_id


How to increment row object_id on condition in mysql?

这是示例表:

id | object_class | object_id | name     |
1  | 1            | 1         | potato   |
2  | 1            | 2         | tomato   |
3  | 2            | 1         | wheel    |
4  | 2            | 2         | seat     |

id 自动递增。例如,我想在object_class等于 1 时添加行。我如何告诉 mysql 在创建新行时,检查对象类中的object_id,找到最大的一个并创建具有 object_id+1 的行?如果object_class不存在,请创建object_id从 1 开始的新行?所以它补充说:

5 | 1             | 3         | foo     | (for existing)
6 | 3             | 1         | bar     | (for new object_class)

我确实知道我可以以某种方式(如果以上是不可能的,请解释通过很少查询的最佳优化方法)获取某些object_class object_id,然后找到最大的一个。之后,使用手动计算的object_id创建新行。但这似乎有很多工作要做。

我想指出的是,我对 mysql 表优化了解不多。

另外,我使用laravel 5框架。

编辑:
刚刚注意到拉拉维尔有聚合MAX http://laravel.com/docs/5.0/queries获取最大值然后使用 max+1 创建新行是好方法吗?

有四种方法可以实现此目的。

  1. 在你的 php 代码中做所有事情。添加行,查询数据库以获取最大值。创建新记录。所有这些都是在 php 中完成的,自动提交设置为 false。如果出现问题,您希望能够回滚。要么一切都按计划进行,两行按预期插入,要么什么都不插入。
  2. 这与上述相同。所有 php,但不是在数据库中搜索最大值,而是保留一个缓存。步骤是这样的:插入行,搜索缓存以查找所需内容,插入第二行,更新缓存。这会更快,但这很麻烦,因为您必须考虑内存问题。是一些简单的数据结构,还是提供这种功能的框架?这些从一开始就很难决定。
  3. 创建一个ON INSERT运行的过程。插入行时,此触发器将被激活,它将运行 SQL 代码。该过程将检查最大值,然后插入新行。
  4. 与 2 相同,但运行您可以通过 php 运行您的过程,而不是通过触发器。

我完全支持案例 1 和 2。我倾向于尽可能避免程序和触发器。我不希望我的业务逻辑到处都是。我尝试将所有内容保留在我的代码中,因为它更易于维护且更易于调试。此外,日志记录也更容易。不熟悉代码库的人可以毫不费力地执行这些步骤。当然,这是我的方法,不一定是正确的方法。在某些情况下,通过代码甚至触发器调用的过程可能非常有效,但我在您的情况下看不到这一点。

在 1 和 2 之间做出决定,这很棘手。这取决于您的应用和您想要实现的目标。1 很简单,如果速度很慢,您可以尝试通过索引进行优化。如果这有效,那就去吧。简单多了。如果没有,那么您必须考虑案例 2。为所需的值保留缓存,而不是查询数据库。在启动时,您初始化缓存(这在启动时完成一次,所以即使它有点慢,也只是一次)。然后使缓存保持最新。如果一些简单和定制的东西是可以的,那么很好。如果没有,那么你开始寻找一些处理这种东西的框架。

这是我的两分钱。我希望这是有帮助的。玩得愉快

@zerkms提供了一些非常有用的见解。您始终会遇到并发问题。所以基本上我知道两种解决这个问题的方法。

  1. 进行交易时的全锁表(悲观锁)(所有三个步骤)。当一个事务发生时,没有其他交易可以做同样的事情,否则它会弄乱你所追求的最大值的查询。不建议这样做,尤其是在应用程序打算提供某些流量的情况下。
  2. 将所需的值保持在同步结构中。检查案例 2。建议这样做。这样,瓶颈只会发生在快速查找时,而不是用于完整的数据库事务。