104 lines
4.1 KiB
Python
104 lines
4.1 KiB
Python
"""PROD数据库 UUID 迁移 — 保留现有数据"""
|
|
import pymysql, uuid
|
|
|
|
conn = pymysql.connect(host='db1.prod.zgitm.com', port=3306, user='mokeegateway', password='mokee.', database='mokeegateway', charset='utf8mb4')
|
|
cur = conn.cursor()
|
|
|
|
def uid(): return uuid.uuid4().hex
|
|
|
|
def ex(sql, *args):
|
|
cur.execute(sql, args)
|
|
conn.commit()
|
|
|
|
# 1. 为所有表添加 uuid_id 列(每次单独执行,忽略已存在错误)
|
|
tables = ['sys_system','sys_user','sys_role','sys_menu','sys_api','sys_dict','sys_file','sys_user_system','sys_user_role','sys_role_menu','sys_login_log','sys_operation_log']
|
|
for t in tables:
|
|
try: ex(f"ALTER TABLE {t} ADD COLUMN uuid_id VARCHAR(64) NOT NULL DEFAULT ''")
|
|
except Exception as e: print(f'{t} add col: {e}')
|
|
|
|
# 2. 生成UUID
|
|
for t in tables:
|
|
ex(f"UPDATE {t} SET uuid_id = REPLACE(UUID(),'-','')")
|
|
print('UUID generated')
|
|
|
|
# 3. 收集新旧ID映射(先收集所有,避免 JOIN 更新时列类型冲突)
|
|
id_map = {}
|
|
for t in tables:
|
|
cur.execute(f"SELECT id, uuid_id FROM {t}")
|
|
id_map[t] = {str(old): new for old, new in cur.fetchall()}
|
|
print('ID maps collected')
|
|
|
|
# 4. 先将所有FK列扩大为VARCHAR(64) (允许NULL先)
|
|
print('Modifying FK columns to VARCHAR...')
|
|
for child_tbl, fks in {
|
|
'sys_api': ['system_id'],
|
|
'sys_role': ['system_id'],
|
|
'sys_menu': ['system_id','parent_id'],
|
|
'sys_user_system': ['user_id','system_id'],
|
|
'sys_user_role': ['user_id','role_id'],
|
|
'sys_role_menu': ['role_id','menu_id'],
|
|
'sys_login_log': ['user_id','system_id'],
|
|
'sys_operation_log': ['user_id','system_id'],
|
|
'sys_system': ['created_by','updated_by'],
|
|
}.items():
|
|
for col in fks:
|
|
try: ex(f"ALTER TABLE {child_tbl} MODIFY {col} VARCHAR(64)")
|
|
except: pass
|
|
try: ex("ALTER TABLE sys_role MODIFY created_by VARCHAR(64)")
|
|
except: pass
|
|
try: ex("ALTER TABLE sys_role MODIFY updated_by VARCHAR(64)")
|
|
except: pass
|
|
print('FK columns widened')
|
|
|
|
# 5. 更新外键引用
|
|
fk_updates = {
|
|
'sys_api': {'system_id': 'sys_system'},
|
|
'sys_role': {'system_id': 'sys_system'},
|
|
'sys_menu': {'system_id': 'sys_system'},
|
|
'sys_user_system': {'system_id': 'sys_system', 'user_id': 'sys_user'},
|
|
'sys_user_role': {'user_id': 'sys_user', 'role_id': 'sys_role'},
|
|
'sys_role_menu': {'role_id': 'sys_role', 'menu_id': 'sys_menu'},
|
|
'sys_login_log': {'user_id': 'sys_user', 'system_id': 'sys_system'},
|
|
'sys_operation_log':{'user_id': 'sys_user', 'system_id': 'sys_system'},
|
|
}
|
|
|
|
for child_tbl, fks in fk_updates.items():
|
|
for fk_col, parent_tbl in fks.items():
|
|
# 读取当前FK值,通过id_map转换后更新
|
|
cur.execute(f"SELECT id, {fk_col} FROM {child_tbl}")
|
|
rows = cur.fetchall()
|
|
for row_id, old_fk in rows:
|
|
if old_fk and str(old_fk) in id_map.get(parent_tbl, {}):
|
|
new_fk = id_map[parent_tbl][str(old_fk)]
|
|
ex(f"UPDATE {child_tbl} SET {fk_col}=%s WHERE id=%s", new_fk, row_id)
|
|
print(f'{child_tbl}.{fk_col} updated')
|
|
|
|
# 6. menu parent_id 自引用
|
|
cur.execute(f"SELECT id, parent_id FROM sys_menu WHERE parent_id != '0'")
|
|
for mid, pid in cur.fetchall():
|
|
if str(pid) in id_map['sys_menu']:
|
|
ex(f"UPDATE sys_menu SET parent_id=%s WHERE id=%s", id_map['sys_menu'][str(pid)], mid)
|
|
print('menu parent_id updated')
|
|
|
|
# 7. 切换主键
|
|
for t in tables:
|
|
cur.execute(f"ALTER TABLE {t} DROP PRIMARY KEY, DROP COLUMN id, CHANGE uuid_id id VARCHAR(64) NOT NULL, ADD PRIMARY KEY (id)")
|
|
print('PK switched')
|
|
|
|
# 8. 重建索引
|
|
try: ex("ALTER TABLE sys_api DROP INDEX uk_system_path_method"); ex("ALTER TABLE sys_api ADD UNIQUE KEY uk_system_path_method (system_id, api_path, api_method)")
|
|
except: pass
|
|
try: ex("ALTER TABLE sys_role DROP INDEX uk_system_role_code"); ex("ALTER TABLE sys_role ADD UNIQUE KEY uk_system_role_code (system_id, role_code)")
|
|
except: pass
|
|
|
|
# 验证
|
|
cur.execute('SELECT id, username FROM sys_user LIMIT 1')
|
|
r = cur.fetchone()
|
|
print(f'验证: user id len={len(str(r[0]))}, username={r[1]}')
|
|
for t in tables:
|
|
cur.execute(f"SELECT COUNT(*) FROM {t}")
|
|
print(f'{t}: {cur.fetchone()[0]}')
|
|
|
|
cur.close(); conn.close()
|
|
print('PROD MIGRATION DONE')
|