修复一个线上1万6千次错误的bug

16.1k mblog.views.getMBlogListByTag

 

MultipleObjectsReturned: get() returned more than one Message -- it returned 2! Lookup parameters were {'photo__id': 2077439L, 'category__in': [1, 9]}

 

这个方法在线上出现16.1k错误,今天终于把这个bug修复了,记录一下处理过程。错误信息显示:

get() returned more than one Message -- it returned 3! Lookup parameters were { 'photo__id': 3288L, 'category__in': [1, 9]}
 

这个错误的意思是说系统认为 category是1,9, photo_id3288的数据 应该是唯一的,但数据库出现了多条记录。数据库查询了一下 select  count(photo_id) from message  group photo_id having count(photo_id) >1 and category in (1,9),发现了1000多条记录。不知道什么原因产生了这种脏数据。现在也无法分析原因了,只能想解决办法。

 

处理过程:

通过代码搜索发现原来这message的getRoot()方法:

  def get_root(self):
        try:
            self.photo
        except:
            return

        key = "photo:root:%s:" % self.photo.id
        root = cache.get(key)
        if root is None:
            try:
                root = self.category in [1, 9] and \
                    self or Message.objects.get(photo__id=self.photo_id, category__in=[1, 9], status__in=[0, 6])[0]
            except Message.DoesNotExist:
                pass
            if root:
                cache.set(key, root, 3600 * 2)

        return root and root.status != 5 and root or None

 里面的get其实存在大于1这种情况的。修改为:

 

   if root is None:
            try:
                root = self.category in [1, 9] and \
                    self or Message.objects.filter(photo__id=self.photo_id, category__in=[1, 9], status__in=[0, 6])[0]
            except Message.DoesNotExist:
                pass
            except IndexError:
                pass

 

 

小结:

    对于这种业务上的唯一性,一定要通过数据库保证唯一性约束

 

 

 

 

 

 

 

你可能感兴趣的:(bug)