-- ========================================================================= -- 存量升级:D9 人脸特征多算法版本(v1.2 → v1.3) -- -- 背景:v1.2 的 lock_face 只有一组 feature_data/feature_algo_version, -- 同一人员按算法 v1 提取后再按 v2 提取会覆盖旧值,算法版本为 v1 的门锁 -- 随即失去可用特征。D9 新增 lock_face_feature: -- 一个 (face_id, algo_version) 一行,一人多版本共存; -- 下发时按目标门锁 lock_device.face_algo_version 选对应版本; -- lock_face 保留图片与「最近一次成功提取」的镜像,旧接口不受影响。 -- -- 执行前置: -- 1) 停止应用(至少停止授权下发与人脸提取); -- 2) 备份 lock_face; -- 3) 先执行本脚本,再发布包含 D9 代码的版本。旧代码不认识新表,可继续 -- 运行(仍读写 lock_face 旧列),但新代码在匹配不到特征时会阻断下发。 -- -- 可重复执行:建表用 if not exists,回填只补缺失行,不覆盖运行期新数据。 -- ========================================================================= set names utf8mb4; -- ========================================================================= -- 1、人脸特征-算法版本表 -- ========================================================================= create table if not exists lock_face_feature ( feature_id bigint(20) not null auto_increment comment '特征ID', face_id bigint(20) not null comment '人脸ID(lock_face.face_id)', person_id bigint(20) not null comment '人员ID(lock_person.person_id)', person_no varchar(32) not null comment '人员编号(冗余协议键,与 lock_face.person_no 一致)', algo_version varchar(32) not null comment '算法版本(提取时使用的 algorithm_version,来自 lock_device.face_algo_version)', feature_data mediumtext comment '人脸特征值(base64编码)', feature_md5 varchar(32) default null comment '特征指纹(变更检测与幂等下发用)', feature_size int(11) default 0 comment '特征字节数', extract_status char(1) default '0' comment '特征提取状态(0未提取 1成功 2失败)', extract_time datetime comment '特征提取时间', extract_msg varchar(512) default null comment '特征提取失败原因', create_by varchar(64) default '' comment '创建者', create_time datetime comment '创建时间', update_by varchar(64) default '' comment '更新者', update_time datetime comment '更新时间', remark varchar(500) default null comment '备注', primary key (feature_id), unique key uk_lock_face_feature_algo (face_id, algo_version), key idx_lock_face_feature_person (person_no, algo_version), key idx_lock_face_feature_person_id (person_id) ) engine=innodb comment = '人脸特征-算法版本表'; -- ========================================================================= -- 2、回填:lock_face 最近一次成功提取的特征转成对应版本的一行 -- - 只回填有特征值且有算法版本的记录;无版本的旧数据无法归位, -- 由人脸管理页按门锁版本重新提取(下发前会阻断并提示)。 -- - 只插入缺失行,重复执行不会覆盖运行期已提取的更优数据。 -- ========================================================================= insert into lock_face_feature ( face_id, person_id, person_no, algo_version, feature_data, feature_md5, feature_size, extract_status, extract_time, extract_msg, create_by, create_time, update_by, update_time, remark ) select f.face_id, f.person_id, f.person_no, trim(f.feature_algo_version), f.feature_data, f.feature_md5, coalesce(f.feature_size, 0), coalesce(f.extract_status, '1'), f.extract_time, f.extract_msg, 'migrate', now(), 'migrate', now(), 'D9 存量回填' from lock_face f where f.del_flag = '0' and f.feature_data is not null and trim(coalesce(f.feature_algo_version, '')) <> '' and not exists ( select 1 from lock_face_feature x where x.face_id = f.face_id and x.algo_version = trim(f.feature_algo_version) ); -- ========================================================================= -- 3、执行后核对(只读,按需执行) -- ========================================================================= -- 3.1 回填条数:应与「有特征且有版本」的人脸数一致 -- select (select count(1) from lock_face_feature) as feature_cnt, -- (select count(1) from lock_face -- where del_flag = '0' and feature_data is not null -- and trim(coalesce(feature_algo_version, '')) <> '') as migratable_cnt; -- -- 3.2 仍未归位的旧特征(有特征值但无算法版本,需按门锁版本重新提取) -- select face_id, person_no, extract_status, extract_time -- from lock_face -- where del_flag = '0' and feature_data is not null -- and trim(coalesce(feature_algo_version, '')) = ''; -- -- 3.3 唯一约束自检:同一人脸同一版本不应多行 -- select face_id, algo_version, count(1) c -- from lock_face_feature group by face_id, algo_version having c > 1; -- -- 3.4 人员编号与主表是否一致(应返回空) -- select ff.feature_id, ff.person_no, f.person_no as face_person_no -- from lock_face_feature ff join lock_face f on f.face_id = ff.face_id -- where ff.person_no <> f.person_no; -- ========================================================================= -- 4、回滚 -- 先回退到不含 D9 的应用版本,再执行: -- drop table if exists lock_face_feature; -- lock_face 的 feature_data/feature_algo_version 等旧列未被本脚本改写, -- 回退后旧代码可继续按单特征模型工作。 -- =========================================================================