如何在mysql的条件下增加row object_id?

时间:2015-03-12 19:27:24

标签: php mysql laravel laravel-5

这是示例表:

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

id自动增量。例如,我想在等于1时为object_class添加行。如何告诉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框架。

编辑:
刚注意到laravel有Aggregate MAX http://laravel.com/docs/5.0/queries 是获得最大值然后用max + 1创建新行的好方法吗?

1 个答案:

答案 0 :(得分:0)

有四种方法可以实现这一目标。

  1. 在您的PHP代码中执行所有操作。添加行,查询数据库以获取最大值。创建新记录。所有这些都是在php中完成的,autocommit设置为false。如果出现问题,您希望能够回滚。要么一切按计划进行,要么按照应该插入两行,否则不插入任何内容。
  2. 这与上述相同。所有的PHP,但不是搜索数据库的最大值,而是保留缓存。步骤如下:插入行,在缓存中搜索需要的内容,插入第二行,更新缓存。这将更快,但它很麻烦,因为你必须考虑内存问题。是一些简单的数据结构,还是一些提供这种功能的框架?这些很难从一开始就决定。
  3. 制作一个运行ON INSERT的程序。插入行时,此触发器将被激活,它将运行SQL代码。该过程将检查max,然后插入新行。
  4. 与2相同,但是运行你可以通过php运行你的程序,而不是通过触发器。
  5. 我全都是针对案例1和2.我倾向于尽可能避免程序和触发器。我不希望我的业务逻辑全面到位。我尝试将所有内容保存在代码中,因为它更易于维护且更易于调试。记录也更容易。对代码库不熟悉的人可以更省力地执行这些步骤。当然,这是我的方法,但不一定是正确的方法。在某些情况下,通过代码或甚至通过触发器调用的过程可能非常有效,但我不会在您的情况下看到这一点。

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

    我的两分钱。我希望这可以帮到你。玩得开心

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

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