insert-into-on-duplicate-key-auto-increment-id跳过

sczxawaw  于 2021-06-21  发布在  Mysql
关注(0)|答案(4)|浏览(423)

我现在有一个sql执行脚本,它更新了duplicate key上的行,如下所示。

$stmt = $dbCon->prepare("INSERT INTO videos_rating (videos_rating_video_fk, "
            . " videos_rating_user_fk, "
            . " videos_rating_rating) "
            . " VALUES (:video_id, "
            . " :user_id, "
            . " :video_rating) "
            . " ON DUPLICATE KEY UPDATE videos_rating_rating = :video_rating");

这个脚本运行得很好,但是有没有办法防止自动递增列失去同步?
假设我们从一个空表开始,我对一个视频进行评级,然后创建一个id为1的行,然后用户再次执行sql,对同一个视频进行较低或较高的评级,该行将被更新,因为它现在是一个重复的键,当然没有问题。
问题是这个。
下一次,当另一个用户对一个新视频进行评分时,该行现在将从id 3开始,而不是从id 2开始?
这张table看起来像这样

id | videos_rating_user_fk | videos_rating_rating
1  | 1                     | 4
3  | 2                     | 5

我找不到一个类似的问题,即使我觉得很可能没有人被这个问题困扰,如果是这样,请把我转到那个帖子。
我知道ids不应该看起来很好,但是ids从30-51-82-85-89等等跳出来是很烦人的,当达到最大无符号大整数时,会不会有问题呢?我不是说我会走那么高,但仍然。

pjngdqdw

pjngdqdw1#

与身份证“燃烧”一起生活。 AUTO_INCREMENT 保证不允许重复值,不提供任何其他保证。
ID可能被“烧掉”的方式还有4种: REPLACE ,多主/galera, IGNORE , DELETE ,可能更多。
iodku在发现语句会变成 UPDATE 不需要id。否则可能会对性能造成重大影响。

hs1rzwqc

hs1rzwqc2#

假设您的表是这样构建的:

videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------

第一把钥匙 videos_rating_video_fk 应该是外键,而不是自动递增的主键。
如果用户1和2投票给具有 id 1、你的table应该是这样的:

videos_rating_video_fk | videos_rating_user_fk | videos_rating_rating
-----------------------+-----------------------+----------------------
1                      | 1                     | 4
1                      | 2                     | 5

对于这种表,主键应该是两个外键的组合,并且是唯一的。用户只能为一个视频投票一次(unique vote=unique key)。一个视频可以由多个用户投票,用户可以为多个视频投票。
我建议您看看merise方法,该方法用于构建具有完整性约束的表和创建主键。

shyt4zoc

shyt4zoc3#

为了证实这一点,保罗·斯皮格尔的回答帮助我解决了这个问题。我有一个'upsert'sql查询 ON DUPLICATE KEY UPDATE 确定是创建新行还是更新现有行。当一行被频繁更新时,分配的id中的跳转就很大。
“问题”是引擎将在知道它是否是重复的id之前“保留”id。
我通过将sql代码分解为单独的insert和update语句来解决这个问题。我再也看不到这个问题了。

kpbwa7wx

kpbwa7wx4#

我假设您使用的是默认的innodb引擎。在这种情况下,“问题”是引擎将“保留”id,然后才知道它是否是重复的。一旦id被“保留”,它就不能被释放,因为另一个线程(另一个用户)可能会在“相同”的时间执行对同一个表的插入。还有其他方法可以在不删除任何行的情况下获取auto\u increment列中的间距。一种是回滚事务。
您可以尝试在每次插入后使用“重置”下一个自动增量值

alter table videos_rating auto_increment = 1;

但我不能说在运行的实时环境中执行此语句可能会遇到什么问题。我不会发现的。
请注意,这通常不是问题,因为运行iodku statemts(通常)的表不需要自动递增列。正如cid在他的回答中所写的,你可以放弃 id 列并将唯一键定义为主键。

相关问题