228 lines
7.9 KiB
Python
228 lines
7.9 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('')
|
|
print('=' * 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('')
|
|
print('=' * 70)
|
|
print('删除 users.referred_by 冗余字段')
|
|
print('=' * 70)
|
|
|
|
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
|
|
''')
|
|
connection.commit()
|
|
|
|
cursor.execute('SELECT COUNT(*) FROM users_referred_by_backup')
|
|
backup_count = cursor.fetchone()[0]
|
|
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('这些记录已备份到 users_referred_by_backup 表')
|
|
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('')
|
|
print('=' * 70)
|
|
print('优化完成!')
|
|
print('=' * 70)
|
|
print('')
|
|
print('后续步骤:')
|
|
print('1. 修改代码中所有使用 referred_by 的地方(已完成)')
|
|
print('2. 部署新代码到服务器')
|
|
print('3. 测试绑定和佣金功能')
|
|
print('4. 确认无误后,可删除备份表: DROP TABLE users_referred_by_backup')
|
|
print('')
|
|
print('备份表可保留一段时间,确保数据安全。')
|
|
|
|
except Exception as e:
|
|
print('')
|
|
print('错误: {}'.format(str(e).encode('utf-8', errors='replace').decode('utf-8', errors='replace')))
|
|
if connection:
|
|
connection.rollback()
|
|
print('已回滚所有更改')
|
|
sys.exit(1)
|
|
|
|
finally:
|
|
if connection:
|
|
cursor.close()
|
|
connection.close()
|
|
print('')
|
|
print('数据库连接已关闭')
|
|
|
|
if __name__ == '__main__':
|
|
print('')
|
|
print('即将自动执行删除 users.referred_by 字段...')
|
|
print('')
|
|
main()
|