我现在有一个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等等跳出来是很烦人的,当达到最大无符号大整数时,会不会有问题呢?我不是说我会走那么高,但仍然。
4条答案
按热度按时间pjngdqdw1#
与身份证“燃烧”一起生活。
AUTO_INCREMENT
保证不允许重复值,不提供任何其他保证。ID可能被“烧掉”的方式还有4种:
REPLACE
,多主/galera,IGNORE
,DELETE
,可能更多。iodku在发现语句会变成
UPDATE
不需要id。否则可能会对性能造成重大影响。hs1rzwqc2#
假设您的表是这样构建的:
第一把钥匙
videos_rating_video_fk
应该是外键,而不是自动递增的主键。如果用户1和2投票给具有
id
1、你的table应该是这样的:对于这种表,主键应该是两个外键的组合,并且是唯一的。用户只能为一个视频投票一次(unique vote=unique key)。一个视频可以由多个用户投票,用户可以为多个视频投票。
我建议您看看merise方法,该方法用于构建具有完整性约束的表和创建主键。
shyt4zoc3#
为了证实这一点,保罗·斯皮格尔的回答帮助我解决了这个问题。我有一个'upsert'sql查询
ON DUPLICATE KEY UPDATE
确定是创建新行还是更新现有行。当一行被频繁更新时,分配的id中的跳转就很大。“问题”是引擎将在知道它是否是重复的id之前“保留”id。
我通过将sql代码分解为单独的insert和update语句来解决这个问题。我再也看不到这个问题了。
kpbwa7wx4#
我假设您使用的是默认的innodb引擎。在这种情况下,“问题”是引擎将“保留”id,然后才知道它是否是重复的。一旦id被“保留”,它就不能被释放,因为另一个线程(另一个用户)可能会在“相同”的时间执行对同一个表的插入。还有其他方法可以在不删除任何行的情况下获取auto\u increment列中的间距。一种是回滚事务。
您可以尝试在每次插入后使用“重置”下一个自动增量值
但我不能说在运行的实时环境中执行此语句可能会遇到什么问题。我不会发现的。
请注意,这通常不是问题,因为运行iodku statemts(通常)的表不需要自动递增列。正如cid在他的回答中所写的,你可以放弃
id
列并将唯一键定义为主键。