# -*- coding: utf-8 -*- """只读勘察第二轮:确定目标库 + 校验引用完整性。绝不写入。""" import io, sys, pymysql sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') SRC = dict(host='192.168.3.200', user='root', password='PX4fTAAsJ#T!1', database='zentao_dev', charset='utf8mb4', connect_timeout=15) DST = dict(host='192.168.1.161', user='devgps', password='dev@2021GPS', charset='utf8mb4', connect_timeout=15) SID = 9197 src = pymysql.connect(**SRC); scur = src.cursor() dst = pymysql.connect(**DST); dcur = dst.cursor() # 1) 161 上哪个库是活跃测试库:比较最近活动 print('===== 161 各库活跃度 =====') for db in ['zentao_dev', 'zentao_dev_2026']: dcur.execute(f'USE `{db}`') dcur.execute("SELECT COUNT(*), MAX(id) FROM zt_story") c1, m1 = dcur.fetchone() try: dcur.execute("SELECT COUNT(*), MAX(date) FROM zt_action") c2, m2 = dcur.fetchone() except Exception as e: c2, m2 = 'err', str(e) dcur.execute("SELECT MAX(lastEditedDate) FROM zt_story") m3 = dcur.fetchone()[0] print(f'{db}: story数={c1} max_story_id={m1} action数={c2} max_action_date={m2} story最近编辑={m3}') # 2) 200 上 9197 相关行明细 print('\n===== 200 上 9197 相关明细 =====') scur.execute("SELECT * FROM zt_storyspec WHERE story=%s", (SID,)) cols = [d[0] for d in scur.description] for r in scur.fetchall(): print('storyspec:', dict(zip(cols, r))) scur.execute("SELECT project, story, version, `order` FROM zt_projectstory WHERE story=%s", (SID,)) proj_links = scur.fetchall() print('projectstory:', proj_links) scur.execute("""SELECT id, project, execution, name, status, type, assignedTo, deleted FROM zt_task WHERE story=%s""", (SID,)) tasks = scur.fetchall() print('tasks:', tasks) scur.execute("""SELECT id, action, date, actor, LEFT(comment,40) FROM zt_action WHERE objectType='story' AND objectID=%s ORDER BY id""", (SID,)) for r in scur.fetchall(): print('action:', r) # 3) zentao_dev_2026 里已有的 9197 action/file 是什么 print('\n===== zentao_dev_2026 已有 9197 action/file =====') dcur.execute('USE zentao_dev_2026') dcur.execute("""SELECT id, action, date, actor, LEFT(comment,40) FROM zt_action WHERE objectType='story' AND objectID=%s ORDER BY id""", (SID,)) for r in dcur.fetchall(): print('action:', r) dcur.execute("SELECT id, title, pathname, addedBy, addedDate FROM zt_file WHERE objectType='story' AND objectID=%s", (SID,)) for r in dcur.fetchall(): print('file:', r) # 4) 引用完整性:目标库中 product/项目/task id 冲突检查 print('\n===== 目标库引用完整性 =====') dcur.execute("SELECT id, LEFT(name,30), deleted FROM zt_product WHERE id=150") print('目标 product 150:', dcur.fetchone()) scur.execute("SELECT id, LEFT(name,30), deleted FROM zt_product WHERE id=150") print('源 product 150:', scur.fetchone()) for pid in {r[0] for r in proj_links}: dcur.execute("SELECT id, LEFT(name,40), deleted FROM zt_project WHERE id=%s", (pid,)) print(f'目标 project {pid}:', dcur.fetchone()) for tid in [t[0] for t in tasks]: dcur.execute("SELECT id, LEFT(name,40), story, deleted FROM zt_task WHERE id=%s", (tid,)) print(f'目标 task {tid} 冲突检查:', dcur.fetchone()) # 5) zt_story 9197 行全列比对(200 vs zentao_dev_2026) scur.execute("SELECT * FROM zt_story WHERE id=%s", (SID,)) story_cols = [d[0] for d in scur.description] srow = scur.fetchone() dcur.execute("SELECT * FROM zt_story WHERE id=%s", (SID,)) drow = dcur.fetchone() diff = [(c, s, d) for c, s, d in zip(story_cols, srow, drow) if s != d] print('\n===== zt_story 9197 差异列 =====' if diff else '\n===== zt_story 9197 两库完全一致 =====') for c, s, d in diff: print(f' {c}: 200={s!r} vs 161_2026={d!r}') src.close(); dst.close()