Files
soul-yongping/scripts/remove-referred-by-field.py

232 lines
8.1 KiB
Python

# -*- coding: utf-8 -*-
"""
删除 users.referred_by 冗余字段
优化绑定关系存储,只使用 referral_bindings 表
"""
import pymysql
import sys
# 数据库配置(从 lib/db.ts 获取)
DB_CONFIG = {
'host': 'gz-cynosdbmysql-grp-kfcvxbby.sql.tencentcdb.com',
'port': 27815,
'user': 'root',
'password': 'Aa112211',
'database': 'soul_miniprogram',
'charset': 'utf8mb4'
}
def print_step(step, msg):
"""打印步骤信息"""
print('\n' + '=' * 70)
print('步骤 {}: {}'.format(step, msg))
print('=' * 70)
def execute_sql(cursor, sql, params=None):
"""执行SQL并返回影响行数"""
try:
if params:
cursor.execute(sql, params)
else:
cursor.execute(sql)
return cursor.rowcount
except Exception as e:
print('执行失败: {}'.format(str(e)))
raise
def main():
connection = None
try:
print_step(1, '连接数据库')
connection = pymysql.connect(**DB_CONFIG)
cursor = connection.cursor()
print('已连接到数据库: {}'.format(DB_CONFIG['database']))
# ========================================
# 步骤2: 备份当前 referred_by 数据
# ========================================
print_step(2, '备份 referred_by 数据(用于验证)')
cursor.execute('''
SELECT
COUNT(*) as total,
COUNT(referred_by) as has_referrer,
COUNT(DISTINCT referred_by) as unique_referrers
FROM users
''')
stats = cursor.fetchone()
print('当前用户表统计:')
print(' 总用户数: {}'.format(stats[0]))
print(' 有推荐人的用户: {}'.format(stats[1]))
print(' 唯一推荐人数: {}'.format(stats[2]))
# 导出 referred_by 数据到临时表(备份)
cursor.execute('DROP TABLE IF EXISTS users_referred_by_backup')
cursor.execute('''
CREATE TABLE users_referred_by_backup AS
SELECT id, referred_by, created_at
FROM users
WHERE referred_by IS NOT NULL
''')
backup_count = cursor.rowcount
print('已备份 {} 条记录到 users_referred_by_backup 表'.format(backup_count))
# ========================================
# 步骤3: 验证 referral_bindings 数据完整性
# ========================================
print_step(3, '验证 referral_bindings 数据完整性')
cursor.execute('''
SELECT
COUNT(*) as total_bindings,
COUNT(DISTINCT referee_id) as unique_referees,
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_bindings
FROM referral_bindings
''')
binding_stats = cursor.fetchone()
print('推荐绑定表统计:')
print(' 总绑定记录: {}'.format(binding_stats[0]))
print(' 唯一被推荐人: {}'.format(binding_stats[1]))
print(' 当前活跃绑定: {}'.format(binding_stats[2]))
# 检查数据一致性
cursor.execute('''
SELECT COUNT(*) FROM users u
WHERE u.referred_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM referral_bindings rb
WHERE rb.referee_id = u.id
)
''')
inconsistent = cursor.fetchone()[0]
if inconsistent > 0:
print('警告: 发现 {} 个用户在 users.referred_by 有值但 referral_bindings 中无记录'.format(inconsistent))
print('这些记录可能是旧数据,删除字段后将丢失')
else:
print('数据一致性检查通过!')
# ========================================
# 步骤4: 删除 referred_by 相关索引
# ========================================
print_step(4, '删除 referred_by 索引')
# 检查索引是否存在
cursor.execute('''
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = %s
AND table_name = 'users'
AND index_name = 'idx_referred_by'
''', (DB_CONFIG['database'],))
index_exists = cursor.fetchone()[0] > 0
if index_exists:
cursor.execute('ALTER TABLE users DROP INDEX idx_referred_by')
print('已删除索引: idx_referred_by')
else:
print('索引 idx_referred_by 不存在,跳过')
# ========================================
# 步骤5: 删除 referred_by 字段
# ========================================
print_step(5, '删除 users.referred_by 字段')
# 检查字段是否存在
cursor.execute('''
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = %s
AND table_name = 'users'
AND column_name = 'referred_by'
''', (DB_CONFIG['database'],))
field_exists = cursor.fetchone()[0] > 0
if field_exists:
cursor.execute('ALTER TABLE users DROP COLUMN referred_by')
print('已删除字段: users.referred_by')
else:
print('字段 referred_by 不存在,跳过')
# ========================================
# 步骤6: 提交更改
# ========================================
print_step(6, '提交数据库更改')
connection.commit()
print('所有更改已提交!')
# ========================================
# 步骤7: 验证删除结果
# ========================================
print_step(7, '验证删除结果')
cursor.execute('''
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = %s
AND table_name = 'users'
AND column_name = 'referred_by'
''', (DB_CONFIG['database'],))
still_exists = cursor.fetchone()[0] > 0
if still_exists:
print('警告: 字段仍然存在!')
else:
print('验证通过: referred_by 字段已成功删除')
# 检查备份表
cursor.execute('SELECT COUNT(*) FROM users_referred_by_backup')
backup_rows = cursor.fetchone()[0]
print('备份表保留了 {} 条记录(可选择稍后删除)'.format(backup_rows))
# ========================================
# 完成
# ========================================
print('\n' + '=' * 70)
print('优化完成!')
print('=' * 70)
print('\n后续步骤:')
print('1. 修改代码中所有使用 referred_by 的地方')
print('2. 部署新代码到服务器')
print('3. 测试绑定和佣金功能')
print('4. 确认无误后,可删除备份表: DROP TABLE users_referred_by_backup')
print('\n备份表可保留一段时间,确保数据安全。')
except Exception as e:
print('\n错误: {}'.format(str(e)))
if connection:
connection.rollback()
print('已回滚所有更改')
sys.exit(1)
finally:
if connection:
cursor.close()
connection.close()
print('\n数据库连接已关闭')
if __name__ == '__main__':
print('\n' + '=' * 70)
print('删除 users.referred_by 冗余字段')
print('=' * 70)
print('\n此脚本将执行以下操作:')
print('1. 备份 referred_by 数据到 users_referred_by_backup 表')
print('2. 删除 idx_referred_by 索引')
print('3. 删除 users.referred_by 字段')
print('\n警告: 此操作会修改数据库结构!')
print('建议先在测试环境执行。')
try:
raw_input_func = raw_input # Python 2
except NameError:
raw_input_func = input # Python 3
confirm = raw_input_func('\n确认执行?(输入 yes 继续): ')
if confirm.lower() != 'yes':
print('已取消操作')
sys.exit(0)
main()