import struct import sys import datetime PAGE_SIZE = 16384 def read_page(filename): with open(filename, "rb") as f: return f.read(PAGE_SIZE) def parse_datetime8(b): """InnoDB DATETIME(0) 存储为 8 字节整数""" if len(b) != 8: return "" val = int.from_bytes(b, byteorder="big", signed=False) if val == 0: return "" try: year = val >> 46 month = (val >> 42) & 0xF day = (val >> 37) & 0x1F hour = (val >> 32) & 0x1F minute = (val >> 26) & 0x3F second = (val >> 20) & 0x3F return f"{year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}" except Exception: return "" def parse_record(data, offset): """ 简化版:假设表结构固定为 machineID (32字节字符串) key (32字节字符串) register_time (8字节DATETIME) expire_time (8字节DATETIME) order_no (32字节字符串) """ pos = offset machineID = data[pos:pos+32].decode("utf-8", errors="ignore").strip("\x00") pos += 32 key = data[pos:pos+32].decode("utf-8", errors="ignore").strip("\x00") pos += 32 register_time = parse_datetime8(data[pos:pos+8]) pos += 8 expire_time = parse_datetime8(data[pos:pos+8]) pos += 8 order_no = data[pos:pos+32].decode("utf-8", errors="ignore").strip("\x00") pos += 32 return [machineID, key, register_time, expire_time, order_no] def parse_page(filename): page = read_page(filename) records = [] # ⚠️ 简化:这里假设每条记录固定大小 32+32+8+8+32=112 字节 # 实际 InnoDB 是变长的,需要解析页目录和记录头 for i in range(0, PAGE_SIZE, 128): # 每128字节尝试一条 rec = parse_record(page, i) if any(rec): # 至少有一个字段非空 records.append(rec) return records if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python3 innodb_row_parser.py ") sys.exit(1) records = parse_page(sys.argv[1]) print("machineID,key,register_time,expire_time,order_no") for r in records: print(",".join(r))