talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingSchemaInitializer.java
@@ -122,6 +122,10 @@
            columns.put("realname_apply_no", "varchar(32) default null");
            columns.put("realname_response_code", "varchar(32) default null");
            columns.put("realname_response_message", "varchar(512) default null");
            // 门店照片:个人(小微)商户的微信业务开通与微信实名都要这两张图,
            // 企业主体用不到。见 V146 的说明。
            columns.put("store_header_url", "varchar(512) default null");
            columns.put("store_indoor_url", "varchar(512) default null");
            for (Map.Entry<String, String> column : columns.entrySet()) {
                if (!hasColumn("merchant_onboarding_application", column.getKey())) addColumn("merchant_onboarding_application", column.getKey(), column.getValue());
            }
@@ -165,8 +169,16 @@
            jdbc.execute("alter table " + tableName + " add column " + columnName + " " + definition);
            log.info("Merchant onboarding schema: added {}.{}", tableName, columnName);
        } catch (Exception exception) {
            log.warn("Merchant onboarding schema: could not add {}.{} within {}s (table busy); it will be retried on the next restart. cause={}",
                    tableName, columnName, DDL_LOCK_WAIT_TIMEOUT_SECONDS, exception.getClass().getSimpleName());
            // 这里必须是 error 而不是 warn:进件的 INSERT/UPDATE 都显式列出列名,缺列不是"只影响重试功能",
            // 而是商户一提交进件就报 Unknown column。原先只记 warn、应用照常启动,于是症状变成
            // "重启了还是报错、又看不出原因"(2026-09-16 在开发库的 legal_mobile 上实际发生过:
            // 同一轮循环里它后面的列都加成功了,只有它抢锁失败)。日志里直接给出补救语句。
            log.error("Merchant onboarding schema: could not add {}.{} within {}s (table busy); the column is"
                            + " referenced by the onboarding INSERT, so onboarding submissions will fail until it"
                            + " exists. Retried on the next restart, or run manually: alter table {} add column {} {}."
                            + " cause={}",
                    tableName, columnName, DDL_LOCK_WAIT_TIMEOUT_SECONDS, tableName, columnName, definition,
                    exception.getClass().getSimpleName());
        }
    }