一次因为主键设置引发的“数据之谜”
最近在开发一个聊天功能时,我遇到了一个奇怪的问题:明明数据库里有9条符合条件的记录,但查询出来的结果却只有1条。
问题的出现
事情是这样的:我在开发一个聊天功能,用户之间的对话记录需要存储在数据库中。为了方便查询某个用户的对话记录,我在ConversationModel表中使用了user_id字段来标识用户。代码逻辑很简单:先查询某个用户的对话记录总数,然后再获取具体的对话内容。
运行代码后,我发现count的值是9,但conversation_messages的长度却是1。这让我非常困惑:明明数据库里有9条记录,为什么查询出来的结果只有1条呢?
排查过程
一开始,我以为是查询条件写错了,反复检查了代码,确认filter_by(user_id=recipient_uid)的条件没有问题。接着,我怀疑是不是数据库连接出了问题,导致查询结果不一致,但检查后发现数据库连接也是正常的。
然后,我开始怀疑是不是数据库事务隔离级别的问题,甚至去查了SQLAlchemy的文档,看看是不是有什么隐藏的坑。但折腾了半天,依然没有找到原因。
最后,我决定直接查看数据库表结构,这才发现了问题的关键:我把user_id设置成了主键(Primary Key)。
为什么主键会导致这个问题?
在数据库中,主键的唯一作用是唯一标识一条记录。也就是说,主键的值必须是唯一的,不能重复。而我错误地把user_id设置成了主键,这意味着每个user_id只能对应一条记录。
所以,当我执行查询时:
由于user_id是主键,数据库只会返回唯一一条记录,即使实际上有多条记录符合条件。这就是为什么count是9,但查询结果却只有1条的原因。
问题的解决
找到原因后,解决方法就很简单了:去掉user_id的主键约束。因为一个用户可能会有多条对话记录,所以user_id不应该作为主键。正确的做法是使用一个独立的字段(比如id)作为主键,而user_id只作为普通字段。
修改后的表结构如下:
修改后,重新运行代码,count和conversation_messages的结果终于一致了!
反思与总结
这次经历让我深刻体会到,数据库设计中的每一个细节都可能对功能产生重大影响。主键的设置看似简单,但如果用错了地方,就会引发意想不到的问题。以下是我总结的几点经验:
- 主键的唯一性:主键的作用是唯一标识一条记录,不能重复。如果一个字段的值可能重复(比如user_id),就不适合作为主键。
- 数据库设计要结合实际业务:在设计数据库时,一定要结合业务需求,确保表结构和字段设置符合实际场景。
- 排查问题要全面:遇到问题时,不要只盯着代码,还要检查数据库表结构、数据状态等可能的影响因素。
这次经历虽然让我折腾了2个小时,啊啊啊!但也让我学到了很多。希望我的这段“踩坑”经历能对大家有所帮助。如果你也遇到过类似的问题,欢迎在评论区分享你的故事!毕竟,程序员的世界里,解决问题的方式千奇百怪,但最终的目标都是一样的:写出更好的代码,做出更好的产品!