心态崩了!这个问题,困扰了我两个小时

开发
数据库设计中的每一个细节都可能对功能产生重大影响,主键的设置看似简单,但如果用错了地方,就会引发意想不到的问题。

一次因为主键设置引发的“数据之谜”

最近在开发一个聊天功能时,我遇到了一个奇怪的问题:明明数据库里有9条符合条件的记录,但查询出来的结果却只有1条。

问题的出现

事情是这样的:我在开发一个聊天功能,用户之间的对话记录需要存储在数据库中。为了方便查询某个用户的对话记录,我在ConversationModel表中使用了user_id字段来标识用户。代码逻辑很简单:先查询某个用户的对话记录总数,然后再获取具体的对话内容。

count = ConversationModel.query.filter_by(user_id=recipient_uid).count()
print(f"符合条件的记录总数:{count}")

conversation_messages = ConversationModel.query.filter_by(user_id=recipient_uid).all()
print(f"查询到的记录数:{len(conversation_messages)}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

运行代码后,我发现count的值是9,但conversation_messages的长度却是1。这让我非常困惑:明明数据库里有9条记录,为什么查询出来的结果只有1条呢?

排查过程

一开始,我以为是查询条件写错了,反复检查了代码,确认filter_by(user_id=recipient_uid)的条件没有问题。接着,我怀疑是不是数据库连接出了问题,导致查询结果不一致,但检查后发现数据库连接也是正常的。

然后,我开始怀疑是不是数据库事务隔离级别的问题,甚至去查了SQLAlchemy的文档,看看是不是有什么隐藏的坑。但折腾了半天,依然没有找到原因。

最后,我决定直接查看数据库表结构,这才发现了问题的关键:我把user_id设置成了主键(Primary Key)。

为什么主键会导致这个问题?

在数据库中,主键的唯一作用是唯一标识一条记录。也就是说,主键的值必须是唯一的,不能重复。而我错误地把user_id设置成了主键,这意味着每个user_id只能对应一条记录。

所以,当我执行查询时:

conversation_messages = ConversationModel.query.filter_by(user_id=recipient_uid).all()
  • 1.

由于user_id是主键,数据库只会返回唯一一条记录,即使实际上有多条记录符合条件。这就是为什么count是9,但查询结果却只有1条的原因。

问题的解决

找到原因后,解决方法就很简单了:去掉user_id的主键约束。因为一个用户可能会有多条对话记录,所以user_id不应该作为主键。正确的做法是使用一个独立的字段(比如id)作为主键,而user_id只作为普通字段。

修改后的表结构如下:

class ConversationModel(db.Model):
    id = db.Column(db.String, primary_key=True, default=lambda: str(uuid.uuid4()))
    user_id = db.Column(db.String)  # 普通字段,不再作为主键
    message = db.Column(db.String)
    # 其他字段...
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

修改后,重新运行代码,count和conversation_messages的结果终于一致了!

反思与总结

这次经历让我深刻体会到,数据库设计中的每一个细节都可能对功能产生重大影响。主键的设置看似简单,但如果用错了地方,就会引发意想不到的问题。以下是我总结的几点经验:

  • 主键的唯一性:主键的作用是唯一标识一条记录,不能重复。如果一个字段的值可能重复(比如user_id),就不适合作为主键。
  • 数据库设计要结合实际业务:在设计数据库时,一定要结合业务需求,确保表结构和字段设置符合实际场景。
  • 排查问题要全面:遇到问题时,不要只盯着代码,还要检查数据库表结构、数据状态等可能的影响因素。

这次经历虽然让我折腾了2个小时,啊啊啊!但也让我学到了很多。希望我的这段“踩坑”经历能对大家有所帮助。如果你也遇到过类似的问题,欢迎在评论区分享你的故事!毕竟,程序员的世界里,解决问题的方式千奇百怪,但最终的目标都是一样的:写出更好的代码,做出更好的产品!

责任编辑:赵宁宁 来源: 老猫coder
相关推荐

2020-05-02 15:10:53

AI 王者荣耀人工智能

2021-04-29 23:45:07

函数式接口可用性

2021-10-08 08:09:13

Facebook算法DNS

2018-10-17 09:47:38

微博搜索全面技术储备

2024-11-11 14:57:56

JWTSession微服务

2022-08-01 09:43:19

程序员Googlefacebook

2024-11-19 08:36:16

2010-08-18 17:06:02

DB2数据库编译

2013-03-21 10:03:04

Perl

2022-02-16 16:36:55

阿里面试面试流程背景

2021-05-11 16:20:02

网站HTTPHTTPS

2021-08-26 07:43:45

B+ 树索引磁盘

2021-09-13 08:38:42

阿里时间成本

2023-04-21 18:48:18

谷歌人工智能开源

2021-10-11 11:05:30

技术资讯

2021-11-22 07:42:47

税前个税工资

2021-03-01 08:05:09

慢查询SQL

2009-07-01 14:49:52

JSP空间租用

2022-07-01 06:44:42

微信应用伪装应用转生

2012-09-20 09:24:36

编程学习编程开发
点赞
收藏

51CTO技术栈公众号