删除用户导致增量唯一reference_id冲突,如何确保其持续递增?
解决硬删除用户后Reference ID重复冲突的方案
当前的Reference ID生成逻辑依赖现有用户记录的计数,硬删除用户后会导致计数回退,进而生成重复ID触发唯一约束冲突。以下是几个可行的解决思路:
方案一:单独维护前缀-最大序列号映射表
- 创建新的Django模型
ReferenceCounter,包含两个核心字段:prefix:CharField,存储前6位的前缀字符串,设为唯一键last_number:IntegerField,存储该前缀对应的最大序列号
- 生成Reference ID时,通过事务+行锁保证并发安全:
from django.db import transaction # 先计算前缀 first_name_tres = first_name.lower()[0:3].ljust(3,'x') last_name_tres = last_name.lower().translate({ord(i): None for i in 'aeiou'})[0:3].ljust(3,'x') prefix = last_name_tres + first_name_tres with transaction.atomic(): # 锁定对应前缀的记录,避免并发生成重复ID counter, created = ReferenceCounter.objects.select_for_update().get_or_create( prefix=prefix, defaults={'last_number': 0} ) counter.last_number += 1 counter.save() user_ref_count = str(counter.last_number).zfill(3) reference_id = prefix + user_ref_count - 优势:彻底脱离对用户表记录数量的依赖,序列号严格递增;即使删除所有用户,再次生成时也会从之前的最大号继续累加。
方案二:查询前缀下的最大现有序列号
- 放弃计数逻辑,改为直接提取当前前缀下最大的数字部分并加1:
from django.db.models import Max first_name_tres = first_name.lower()[0:3].ljust(3,'x') last_name_tres = last_name.lower().translate({ord(i): None for i in 'aeiou'})[0:3].ljust(3,'x') prefix = last_name_tres + first_name_tres # 查询该前缀下最大的reference_id max_ref = ProfileMember.objects.filter(reference_id__startswith=prefix).aggregate( max_ref=Max('reference_id') )['max_ref'] if max_ref: # 提取最后3位数字并转为整数 last_num = int(max_ref[-3:]) user_ref_count = str(last_num + 1).zfill(3) else: user_ref_count = '001' reference_id = prefix + user_ref_count - 注意:需确保
reference_id格式严格符合前缀+3位数字的规则,高并发场景下建议配合事务使用避免竞态。
方案三:利用数据库序列(PostgreSQL专属)
- 为每个前缀创建独立的数据库序列,生成ID时调用序列的
nextval获取下一个值:first_name_tres = first_name.lower()[0:3].ljust(3,'x') last_name_tres = last_name.lower().translate({ord(i): None for i in 'aeiou'})[0:3].ljust(3,'x') prefix = last_name_tres + first_name_tres from django.db import connection with connection.cursor() as cursor: # 假设序列命名规则为seq_ref_前缀 cursor.execute(f"SELECT nextval('seq_ref_{prefix}')") last_num = cursor.fetchone()[0] user_ref_count = str(last_num).zfill(3) reference_id = prefix + user_ref_count - 优势:数据库层面保证序列递增,无需额外模型维护;但需手动管理序列的创建与迁移。
内容的提问来源于stack exchange,提问作者fmakawa
相关产品推荐
相关产品推荐

