2026-06-10 11:14:49 +08:00

1772 lines
99 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用 utf8mb4 连接字符集,保证中文注释、中文名称和 emoji 在导入时不被降级。
CREATE DATABASE IF NOT EXISTS hyapp_user DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE hyapp_user;
CREATE TABLE IF NOT EXISTS apps (
app_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '应用 ID',
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
app_name VARCHAR(128) NOT NULL COMMENT '应用名称',
package_name VARCHAR(191) NOT NULL COMMENT '包名称',
platform VARCHAR(32) NOT NULL DEFAULT '' COMMENT '平台',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_apps_code (app_code),
UNIQUE KEY uk_apps_package_platform (package_name, platform),
KEY idx_apps_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应用注册表';
INSERT INTO apps (app_code, app_name, package_name, platform, status, created_at_ms, updated_at_ms)
VALUES ('lalu', 'Lalu', 'com.org.laluparty', '', 'active', 0, 0)
ON DUPLICATE KEY UPDATE
app_name = VALUES(app_name),
package_name = VALUES(package_name),
platform = VALUES(platform),
status = VALUES(status),
updated_at_ms = VALUES(updated_at_ms);
CREATE TABLE IF NOT EXISTS users (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID',
default_display_user_id VARCHAR(32) NOT NULL COMMENT '默认展示用户 ID',
current_display_user_id VARCHAR(32) NOT NULL COMMENT '当前展示用户 ID',
current_display_user_id_kind VARCHAR(32) NOT NULL COMMENT '当前展示用户 ID 类型',
current_display_user_id_expires_at_ms BIGINT NULL COMMENT '当前展示用户 ID 过期时间UTC epoch ms',
username VARCHAR(64) NULL COMMENT '用户名',
gender VARCHAR(32) NULL COMMENT '性别',
country VARCHAR(64) NULL COMMENT '国家',
region_id BIGINT NULL COMMENT '区域 ID',
invite_code VARCHAR(64) NULL COMMENT '邀请编码',
register_ip VARCHAR(64) NULL COMMENT '注册IP',
register_user_agent VARCHAR(512) NULL COMMENT '注册用户代理',
country_by_ip VARCHAR(64) NULL COMMENT 'IP 解析国家',
register_device_id VARCHAR(128) NULL COMMENT '注册设备 ID',
register_device VARCHAR(128) NULL COMMENT '注册设备',
os_version VARCHAR(64) NULL COMMENT 'os版本',
avatar VARCHAR(512) NULL COMMENT '头像',
birth_date DATE NULL COMMENT '出生日期',
app_version VARCHAR(64) NULL COMMENT '应用版本',
build_number VARCHAR(64) NULL COMMENT '构建编号',
source VARCHAR(64) NULL COMMENT '来源',
install_channel VARCHAR(64) NULL COMMENT '安装渠道',
campaign VARCHAR(128) NULL COMMENT '投放活动',
platform VARCHAR(16) NULL COMMENT '平台',
language VARCHAR(32) NULL COMMENT '语言',
timezone VARCHAR(64) NULL COMMENT '时区',
profile_completed TINYINT(1) NOT NULL DEFAULT 0 COMMENT '资料完成',
profile_completed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '资料完成时间UTC epoch ms',
onboarding_status VARCHAR(32) NOT NULL DEFAULT 'profile_required' COMMENT '新手引导状态',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_users_default_display_user_id (app_code, default_display_user_id),
UNIQUE KEY uk_users_current_display_user_id (app_code, current_display_user_id),
UNIQUE KEY uk_users_register_device_id (app_code, register_device_id),
KEY idx_users_status (app_code, status),
KEY idx_users_region_status (app_code, region_id, status),
KEY idx_users_country_region (app_code, country, region_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户主数据表';
CREATE TABLE IF NOT EXISTS user_profile_stats (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
visitors_count BIGINT NOT NULL DEFAULT 0 COMMENT '访客数量',
following_count BIGINT NOT NULL DEFAULT 0 COMMENT '关注中数量',
friends_count BIGINT NOT NULL DEFAULT 0 COMMENT '好友数量',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资料统计表';
CREATE TABLE IF NOT EXISTS user_profile_visits (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
visitor_user_id BIGINT NOT NULL COMMENT '访客用户 ID',
visit_count BIGINT NOT NULL DEFAULT 1 COMMENT '访问数量',
first_visited_at_ms BIGINT NOT NULL COMMENT '首次访问时间UTC epoch ms',
last_visited_at_ms BIGINT NOT NULL COMMENT '最后访问时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, target_user_id, visitor_user_id),
KEY idx_user_profile_visits_visitor (app_code, visitor_user_id, last_visited_at_ms),
KEY idx_user_profile_visits_target_time (app_code, target_user_id, last_visited_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资料访问表';
CREATE TABLE IF NOT EXISTS user_follows (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
follower_user_id BIGINT NOT NULL COMMENT '关注人用户 ID',
followee_user_id BIGINT NOT NULL COMMENT '被关注人用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
followed_at_ms BIGINT NOT NULL COMMENT '关注时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, follower_user_id, followee_user_id),
KEY idx_user_follows_followee_status (app_code, followee_user_id, status, updated_at_ms),
KEY idx_user_follows_follower_status (app_code, follower_user_id, status, followed_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户关注表';
CREATE TABLE IF NOT EXISTS user_friend_applications (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
requester_user_id BIGINT NOT NULL COMMENT '申请人用户 ID',
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, requester_user_id, target_user_id),
KEY idx_friend_applications_target_status (app_code, target_user_id, status, updated_at_ms),
KEY idx_friend_applications_requester_status (app_code, requester_user_id, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户好友申请表';
CREATE TABLE IF NOT EXISTS user_friendships (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
friend_user_id BIGINT NOT NULL COMMENT '好友用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
friended_at_ms BIGINT NOT NULL COMMENT '成为好友时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id, friend_user_id),
KEY idx_user_friendships_user_status (app_code, user_id, status, friended_at_ms),
KEY idx_user_friendships_friend_status (app_code, friend_user_id, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户好友关系表';
CREATE TABLE IF NOT EXISTS user_status_change_logs (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
old_status VARCHAR(32) NOT NULL COMMENT '原状态',
new_status VARCHAR(32) NOT NULL COMMENT '新状态',
operator_type VARCHAR(32) NOT NULL COMMENT '操作人类型',
operator_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '操作人用户 ID',
reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '原因',
request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '链路请求 ID用于排查问题',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
KEY idx_user_status_logs_target (app_code, target_user_id, created_at_ms),
KEY idx_user_status_logs_status (app_code, new_status, created_at_ms),
KEY idx_user_status_logs_operator (app_code, operator_type, operator_user_id, created_at_ms),
KEY idx_user_status_logs_request (app_code, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户状态变更日志表';
CREATE TABLE IF NOT EXISTS manager_user_blocks (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
block_id VARCHAR(96) NOT NULL COMMENT '经理封禁记录 ID',
command_id VARCHAR(128) NOT NULL COMMENT '幂等命令 ID',
manager_user_id BIGINT NOT NULL COMMENT '经理用户 ID',
target_user_id BIGINT NOT NULL COMMENT '被封禁用户 ID',
target_display_user_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '被封禁用户短 ID 快照',
target_username VARCHAR(128) NOT NULL DEFAULT '' COMMENT '被封禁用户昵称快照',
target_avatar VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '被封禁用户头像快照',
country VARCHAR(16) NOT NULL DEFAULT '' COMMENT '封禁时双方国家码',
target_old_status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '封禁前用户状态',
blocked_until_ms BIGINT NOT NULL COMMENT '计划解封时间UTC epoch ms',
status VARCHAR(32) NOT NULL COMMENT 'active/released/expired',
reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '封禁原因',
released_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '释放原因',
released_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '释放时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, block_id),
UNIQUE KEY uk_manager_user_blocks_command (app_code, command_id),
KEY idx_manager_user_blocks_manager (app_code, manager_user_id, status, created_at_ms),
KEY idx_manager_user_blocks_target (app_code, target_user_id, status),
KEY idx_manager_user_blocks_expire (app_code, status, blocked_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='经理中心用户封禁记录表';
CREATE TABLE IF NOT EXISTS user_reports (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
report_id VARCHAR(96) NOT NULL COMMENT '举报单业务 ID',
reporter_user_id BIGINT NOT NULL COMMENT '举报发起人用户 ID',
target_type VARCHAR(16) NOT NULL COMMENT '举报目标类型user/room',
target_user_id BIGINT NULL COMMENT '被举报用户 ID',
room_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '被举报房间 ID',
report_type VARCHAR(64) NOT NULL COMMENT '举报类型',
reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '举报理由',
image_urls_json JSON NOT NULL COMMENT '举报图片 URL 数组',
status VARCHAR(32) NOT NULL COMMENT '处理状态',
request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '链路请求 ID用于排查问题',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, report_id),
KEY idx_user_reports_reporter (app_code, reporter_user_id, created_at_ms),
KEY idx_user_reports_target_user (app_code, target_user_id, created_at_ms),
KEY idx_user_reports_room (app_code, room_id, created_at_ms),
KEY idx_user_reports_status (app_code, status, created_at_ms),
KEY idx_user_reports_request (app_code, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户举报表';
CREATE TABLE IF NOT EXISTS display_user_id_sequences (
app_code VARCHAR(32) NOT NULL PRIMARY KEY COMMENT '应用编码,用于多租户隔离',
next_value BIGINT NOT NULL COMMENT '下一个值',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='展示用户 ID 序列表';
INSERT INTO display_user_id_sequences (app_code, next_value, updated_at_ms)
VALUES ('lalu', 163000, 0)
ON DUPLICATE KEY UPDATE
next_value = next_value;
CREATE TABLE IF NOT EXISTS countries (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
country_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '国家 ID',
country_name VARCHAR(128) NOT NULL COMMENT '国家名称',
country_code VARCHAR(3) NOT NULL COMMENT '国家或地区编码',
iso_alpha3 VARCHAR(3) NULL COMMENT 'ISO三字码',
iso_numeric CHAR(3) NULL COMMENT 'ISO数字',
country_display_name VARCHAR(128) NOT NULL COMMENT '国家展示名称',
phone_country_code VARCHAR(8) NULL COMMENT '电话国家编码',
flag VARCHAR(16) NOT NULL DEFAULT '' COMMENT '国旗',
enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '启用',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_countries_code (app_code, country_code),
UNIQUE KEY uk_countries_iso_numeric (app_code, iso_numeric),
KEY idx_countries_phone_country_code (app_code, phone_country_code),
KEY idx_countries_app_enabled_sort (app_code, enabled, sort_order, country_code),
KEY idx_countries_sort (app_code, sort_order, country_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='国家表';
CREATE TABLE IF NOT EXISTS regions (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
region_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '区域 ID',
region_code VARCHAR(64) NOT NULL COMMENT '区域编码',
name VARCHAR(128) NOT NULL COMMENT '名称',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_regions_code (app_code, region_code),
KEY idx_regions_status_sort (app_code, status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='区域表';
CREATE TABLE IF NOT EXISTS region_countries (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
country_code VARCHAR(3) NOT NULL COMMENT '国家或地区编码',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
active_country_code VARCHAR(3)
GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN country_code ELSE NULL END
) STORED COMMENT '启用国家编码',
UNIQUE KEY uk_region_countries_active_country (app_code, active_country_code),
KEY idx_region_countries_country_status (app_code, country_code, status),
KEY idx_region_countries_region_status (app_code, region_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='区域国家表';
CREATE TABLE IF NOT EXISTS region_change_logs (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
region_id BIGINT NULL COMMENT '区域 ID',
operation VARCHAR(64) NOT NULL COMMENT '操作',
before_json JSON NULL COMMENT '变更前 JSON 快照',
after_json JSON NULL COMMENT '变更后 JSON 快照',
operator_user_id BIGINT NULL COMMENT '操作人用户 ID',
request_id VARCHAR(96) NOT NULL COMMENT '链路请求 ID用于排查问题',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
KEY idx_region_change_logs_region (app_code, region_id, created_at_ms),
KEY idx_region_change_logs_request_id (app_code, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='区域变更日志表';
CREATE TABLE IF NOT EXISTS user_region_rebuild_tasks (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
task_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '任务 ID',
region_id BIGINT NULL COMMENT '区域 ID',
country_code VARCHAR(3) NOT NULL COMMENT '国家或地区编码',
target_region_id BIGINT NULL COMMENT '目标区域 ID',
mapping_revision BIGINT NOT NULL COMMENT '映射版本',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
cursor_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '游标用户 ID',
locked_by VARCHAR(128) NULL COMMENT '当前锁定 worker',
locked_until_ms BIGINT NULL COMMENT '锁定截止时间UTC epoch ms',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
error_message VARCHAR(512) NULL COMMENT '错误消息',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
KEY idx_user_region_rebuild_tasks_status (app_code, status, updated_at_ms),
KEY idx_user_region_rebuild_tasks_country (app_code, country_code, status),
KEY idx_user_region_rebuild_tasks_lock (app_code, status, locked_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户区域重建任务表';
CREATE TABLE IF NOT EXISTS user_push_tokens (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
device_id VARCHAR(128) NOT NULL COMMENT '设备 ID',
push_token VARCHAR(512) NOT NULL COMMENT '推送令牌',
provider VARCHAR(32) NOT NULL COMMENT '提供方',
platform VARCHAR(16) NOT NULL COMMENT '平台',
app_version VARCHAR(64) NOT NULL DEFAULT '' COMMENT '应用版本',
language VARCHAR(32) NOT NULL DEFAULT '' COMMENT '语言',
timezone VARCHAR(64) NOT NULL DEFAULT '' COMMENT '时区',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
bound_at_ms BIGINT NOT NULL COMMENT '绑定时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
last_request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '最后请求 ID',
PRIMARY KEY (app_code, user_id, device_id),
UNIQUE KEY uk_user_push_tokens_token (app_code, provider, push_token),
KEY idx_user_push_tokens_user_status (app_code, user_id, status),
KEY idx_user_push_tokens_updated (app_code, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户推送令牌表';
CREATE TABLE IF NOT EXISTS user_invite_codes (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
invite_code_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '邀请码 ID',
owner_user_id BIGINT NOT NULL COMMENT '房主用户 ID',
code VARCHAR(64) NOT NULL COMMENT '编码',
code_type VARCHAR(32) NOT NULL DEFAULT 'primary' COMMENT '编码类型',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_user_invite_codes_code (app_code, code),
UNIQUE KEY uk_user_invite_codes_owner_primary (app_code, owner_user_id, code_type),
KEY idx_user_invite_codes_owner (app_code, owner_user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请编码表';
CREATE TABLE IF NOT EXISTS user_invite_relations (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
relation_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '关系 ID',
invited_user_id BIGINT NOT NULL COMMENT '被邀请人用户 ID',
inviter_user_id BIGINT NOT NULL COMMENT '邀请人用户 ID',
invite_code_id BIGINT NOT NULL COMMENT '邀请码 ID',
invite_code VARCHAR(64) NOT NULL COMMENT '邀请编码',
source VARCHAR(64) NOT NULL COMMENT '来源',
request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '链路请求 ID用于排查问题',
bound_at_ms BIGINT NOT NULL COMMENT '绑定时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_user_invite_relations_invited (app_code, invited_user_id),
KEY idx_user_invite_relations_inviter (app_code, inviter_user_id, bound_at_ms),
KEY idx_user_invite_relations_code (app_code, invite_code, bound_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请关系表';
CREATE TABLE IF NOT EXISTS user_invite_validity_policies (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
policy_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '策略 ID',
region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域 ID',
policy_version VARCHAR(64) NOT NULL COMMENT '策略版本',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
required_recharge_coin_amount BIGINT NOT NULL COMMENT '要求充值金币数量',
eligible_recharge_types JSON NOT NULL COMMENT '可计入充值类型',
effective_from_ms BIGINT NOT NULL COMMENT '生效开始时间UTC epoch ms',
effective_to_ms BIGINT NULL COMMENT '生效结束时间UTC epoch ms',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_user_invite_policy_version (app_code, region_id, policy_version),
KEY idx_user_invite_policies_active (app_code, region_id, status, effective_from_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请有效性策略表';
INSERT INTO user_invite_validity_policies (
app_code, region_id, policy_version, status, required_recharge_coin_amount,
eligible_recharge_types, effective_from_ms, effective_to_ms, created_by_user_id, created_at_ms, updated_at_ms
) VALUES (
'lalu', 0, 'invite-valid-default-v1', 'active', 80000,
JSON_ARRAY('coin_seller_transfer'), 0, NULL, NULL, 0, 0
) ON DUPLICATE KEY UPDATE
status = VALUES(status),
required_recharge_coin_amount = VALUES(required_recharge_coin_amount),
eligible_recharge_types = VALUES(eligible_recharge_types),
effective_from_ms = VALUES(effective_from_ms),
effective_to_ms = VALUES(effective_to_ms),
updated_at_ms = VALUES(updated_at_ms);
CREATE TABLE IF NOT EXISTS user_invite_recharge_progress (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
invited_user_id BIGINT NOT NULL COMMENT '被邀请人用户 ID',
inviter_user_id BIGINT NOT NULL COMMENT '邀请人用户 ID',
policy_id BIGINT NOT NULL COMMENT '策略 ID',
policy_version VARCHAR(64) NOT NULL COMMENT '策略版本',
required_recharge_coin_amount BIGINT NOT NULL COMMENT '要求充值金币数量',
accumulated_recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金币数量',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
valid_at_ms BIGINT NULL COMMENT '有效时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, invited_user_id),
KEY idx_user_invite_progress_inviter_status (app_code, inviter_user_id, status, updated_at_ms),
KEY idx_user_invite_progress_policy (app_code, policy_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请充值进度表';
CREATE TABLE IF NOT EXISTS user_invite_event_consumption (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
invited_user_id BIGINT NOT NULL COMMENT '被邀请人用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因',
consumed_at_ms BIGINT NULL COMMENT '消费时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, event_id),
UNIQUE KEY uk_user_invite_event_tx (app_code, transaction_id, event_type),
KEY idx_user_invite_event_user (app_code, invited_user_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请事件消费位点表';
CREATE TABLE IF NOT EXISTS user_invite_counters (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
invite_count BIGINT NOT NULL DEFAULT 0 COMMENT '邀请数量',
valid_invite_count BIGINT NOT NULL DEFAULT 0 COMMENT '有效邀请数量',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户邀请计数表';
CREATE TABLE IF NOT EXISTS user_cp_relation_configs (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
relation_type VARCHAR(32) NOT NULL COMMENT '关系类型cp、brother、sister',
max_count_per_user INT NOT NULL COMMENT '每个用户可拥有的该类型 active 关系数量上限',
application_expire_hours INT NOT NULL COMMENT '申请过期小时数',
breakup_cost_coins BIGINT NOT NULL DEFAULT 0 COMMENT '用户主动解除该类型关系需要支付的金币数',
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, relation_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 关系配置表';
CREATE TABLE IF NOT EXISTS user_cp_level_rules (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
relation_type VARCHAR(32) NOT NULL COMMENT '关系类型cp、brother、sister',
level_no INT NOT NULL COMMENT '关系等级1-5',
intimacy_threshold BIGINT NOT NULL COMMENT '达到该等级需要的亲密值',
reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '升级发放的装扮资源组 ID0 表示不发放',
level_icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '等级展示图标',
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, relation_type, level_no),
KEY idx_user_cp_level_rules_status (app_code, status, relation_type, level_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 等级规则表';
CREATE TABLE IF NOT EXISTS user_cp_applications (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
application_id VARCHAR(128) NOT NULL COMMENT '申请 ID',
requester_user_id BIGINT NOT NULL COMMENT '发起用户 ID',
target_user_id BIGINT NOT NULL COMMENT '接收用户 ID',
relation_type VARCHAR(32) NOT NULL COMMENT '关系类型cp、brother、sister',
status VARCHAR(32) NOT NULL COMMENT '申请状态pending、accepted、rejected、expired、blocked',
room_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '触发礼物所在房间 ID',
room_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '触发礼物所在房间区域 ID',
gift_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '触发申请的礼物 ID',
gift_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '触发申请的礼物名称',
gift_icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '触发申请的礼物图标',
gift_animation_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '触发申请的礼物动画',
gift_count INT NOT NULL DEFAULT 0 COMMENT '触发申请的礼物数量',
gift_value BIGINT NOT NULL DEFAULT 0 COMMENT '触发申请的礼物亲密值/热度值',
billing_receipt_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包扣费回执 ID',
source_room_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '来源 room outbox 事件 ID',
source_command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '来源房间命令 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
expires_at_ms BIGINT NOT NULL COMMENT '过期时间UTC epoch ms',
decided_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '同意或拒绝时间UTC epoch ms',
PRIMARY KEY (app_code, application_id),
UNIQUE KEY uk_user_cp_app_source_event (app_code, source_room_event_id),
KEY idx_user_cp_app_target_status (app_code, target_user_id, status, updated_at_ms),
KEY idx_user_cp_app_requester_status (app_code, requester_user_id, status, updated_at_ms),
KEY idx_user_cp_app_pair_status (app_code, requester_user_id, target_user_id, status, relation_type),
KEY idx_user_cp_app_expire (app_code, status, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 关系申请表';
CREATE TABLE IF NOT EXISTS user_cp_relationships (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
relationship_id VARCHAR(128) NOT NULL COMMENT '关系 ID',
user_a_id BIGINT NOT NULL COMMENT '较小的用户 ID',
user_b_id BIGINT NOT NULL COMMENT '较大的用户 ID',
relation_type VARCHAR(32) NOT NULL COMMENT '关系类型cp、brother、sister',
status VARCHAR(32) NOT NULL COMMENT '关系状态active、ended',
intimacy_value BIGINT NOT NULL DEFAULT 0 COMMENT '两人关系亲密值',
level_no INT NOT NULL DEFAULT 1 COMMENT '当前关系等级',
source_application_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '建立关系的申请 ID',
formed_at_ms BIGINT NOT NULL COMMENT '建立时间UTC epoch ms',
ended_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '解除时间UTC epoch ms',
ended_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '主动解除关系的用户 ID',
breakup_cost_coins BIGINT NOT NULL DEFAULT 0 COMMENT '本次解除实际支付金币数',
breakup_command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '解除关系命令 ID',
breakup_wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '解除扣费钱包交易 ID',
breakup_coin_balance_after BIGINT NOT NULL DEFAULT 0 COMMENT '解除扣费后用户金币余额',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, relationship_id),
UNIQUE KEY uk_user_cp_rel_active_pair (app_code, user_a_id, user_b_id, status),
KEY idx_user_cp_rel_user_a (app_code, user_a_id, status, relation_type, updated_at_ms),
KEY idx_user_cp_rel_user_b (app_code, user_b_id, status, relation_type, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 关系表';
CREATE TABLE IF NOT EXISTS user_cp_relationship_breakups (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
command_id VARCHAR(128) NOT NULL COMMENT '解除关系命令 ID',
relationship_id VARCHAR(128) NOT NULL COMMENT '关系 ID',
requester_user_id BIGINT NOT NULL COMMENT '发起解除的用户 ID',
relation_type VARCHAR(32) NOT NULL COMMENT '关系类型cp、brother、sister',
breakup_cost_coins BIGINT NOT NULL DEFAULT 0 COMMENT '创建解除占位时读取到的金币费用',
status VARCHAR(32) NOT NULL COMMENT '解除状态pending、confirmed、canceled',
wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '解除扣费钱包交易 ID',
coin_balance_after BIGINT NOT NULL DEFAULT 0 COMMENT '扣费后金币余额',
reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '取消原因',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
confirmed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '确认解除时间UTC epoch ms',
canceled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '取消解除时间UTC epoch ms',
PRIMARY KEY (app_code, command_id),
KEY idx_user_cp_breakup_relationship_status (app_code, relationship_id, status, updated_at_ms),
KEY idx_user_cp_breakup_requester_status (app_code, requester_user_id, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 关系解除占位表';
CREATE TABLE IF NOT EXISTS user_cp_gift_event_consumption (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
room_event_id VARCHAR(128) NOT NULL COMMENT 'room outbox 事件 ID',
status VARCHAR(32) NOT NULL COMMENT '消费状态',
application_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '生成或刷新申请 ID',
relationship_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '命中的 active 关系 ID',
skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因',
consumed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '消费时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, room_event_id),
KEY idx_user_cp_gift_consumption_status (app_code, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 礼物事件消费位点表';
CREATE TABLE IF NOT EXISTS user_outbox (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型',
aggregate_id BIGINT NOT NULL COMMENT '聚合 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'MQ 投递 worker ID',
lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'MQ 投递锁过期时间UTC epoch ms',
retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次 MQ 投递重试时间UTC epoch ms',
last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最后一次失败原因',
payload_json JSON NOT NULL COMMENT '业务负载 JSON 快照',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, event_id),
KEY idx_user_outbox_status_created (app_code, status, next_retry_at_ms, created_at_ms, event_id),
KEY idx_user_outbox_lock (app_code, status, lock_until_ms, created_at_ms, event_id),
KEY idx_user_outbox_retention (app_code, status, updated_at_ms, event_id),
KEY idx_user_outbox_aggregate (app_code, aggregate_type, aggregate_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户发件箱表';
-- 老测试库可能已经存在 user_outboxCREATE TABLE IF NOT EXISTS 不会补齐后续新增的 MQ 投递字段。
-- 这里用 information_schema 生成幂等 ALTER保证重复执行 initdb 时不会因重复列名失败。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND COLUMN_NAME = 'worker_id') = 0,
'ALTER TABLE user_outbox ADD COLUMN worker_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''MQ 投递 worker ID'' AFTER status',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 投递锁过期时间用于多实例 claim user_outbox老库缺这个列时 CP 通知 worker 会直接 SQL 1054。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND COLUMN_NAME = 'lock_until_ms') = 0,
'ALTER TABLE user_outbox ADD COLUMN lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''MQ 投递锁过期时间UTC epoch ms'' AFTER worker_id',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 重试次数和下一次重试时间跟 outbox 补偿投递扫描绑定,缺列会导致 pending 查询或失败回写不可用。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND COLUMN_NAME = 'retry_count') = 0,
'ALTER TABLE user_outbox ADD COLUMN retry_count INT NOT NULL DEFAULT 0 COMMENT ''重试次数'' AFTER lock_until_ms',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND COLUMN_NAME = 'next_retry_at_ms') = 0,
'ALTER TABLE user_outbox ADD COLUMN next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''下一次 MQ 投递重试时间UTC epoch ms'' AFTER retry_count',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 失败原因用于排查投递链路,缺列时 MarkFailed 会再次失败并掩盖真实业务错误。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND COLUMN_NAME = 'last_error') = 0,
'ALTER TABLE user_outbox ADD COLUMN last_error VARCHAR(512) NOT NULL DEFAULT '''' COMMENT ''最后一次失败原因'' AFTER next_retry_at_ms',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- pending 索引列顺序跟 user_outbox 扫描条件绑定;历史索引存在时先删除再按当前结构重建。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND INDEX_NAME = 'idx_user_outbox_status_created') > 0,
'ALTER TABLE user_outbox DROP INDEX idx_user_outbox_status_created',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := 'ALTER TABLE user_outbox ADD INDEX idx_user_outbox_status_created (app_code, status, next_retry_at_ms, created_at_ms, event_id)';
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND INDEX_NAME = 'idx_user_outbox_lock') = 0,
'ALTER TABLE user_outbox ADD INDEX idx_user_outbox_lock (app_code, status, lock_until_ms, created_at_ms, event_id)',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND INDEX_NAME = 'idx_user_outbox_retention') = 0,
'ALTER TABLE user_outbox ADD INDEX idx_user_outbox_retention (app_code, status, updated_at_ms, event_id)',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_outbox' AND INDEX_NAME = 'idx_user_outbox_aggregate') = 0,
'ALTER TABLE user_outbox ADD INDEX idx_user_outbox_aggregate (app_code, aggregate_type, aggregate_id, created_at_ms)',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
CREATE TABLE IF NOT EXISTS user_mic_sessions (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
mic_session_id VARCHAR(128) NOT NULL COMMENT '麦位会话 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
first_seat_no INT NOT NULL COMMENT '首次麦位编号',
current_seat_no INT NOT NULL COMMENT '当前麦位编号',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
seat_started_at_ms BIGINT NOT NULL COMMENT '麦位开始时间UTC epoch ms',
publishing_started_at_ms BIGINT NULL COMMENT '推流开始时间UTC epoch ms',
ended_at_ms BIGINT NULL COMMENT '结束时间UTC epoch ms',
end_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '结束原因',
seat_occupied_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位占用毫秒值',
mic_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位在线毫秒值',
opened_event_id VARCHAR(128) NOT NULL COMMENT '打开事件 ID',
publish_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '推流事件 ID',
closed_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '关闭事件 ID',
last_event_id VARCHAR(128) NOT NULL COMMENT '最后事件 ID',
last_room_version BIGINT NOT NULL DEFAULT 0 COMMENT '最后房间版本',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, mic_session_id),
KEY idx_user_mic_sessions_user_status (app_code, user_id, status, updated_at_ms),
KEY idx_user_mic_sessions_room_status (app_code, room_id, status),
KEY idx_user_mic_sessions_open_timeout (app_code, status, seat_started_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户麦位会话表';
CREATE TABLE IF NOT EXISTS user_mic_daily_stats (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
stat_date CHAR(10) NOT NULL COMMENT '统计日期',
seat_occupied_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位占用毫秒值',
mic_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位在线毫秒值',
session_count BIGINT NOT NULL DEFAULT 0 COMMENT '会话数量',
room_count BIGINT NOT NULL DEFAULT 0 COMMENT '房间数量',
first_mic_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首次麦位时间UTC epoch ms',
last_mic_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后麦位时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id, stat_date),
KEY idx_user_mic_daily_date (app_code, stat_date, mic_online_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户麦位每日统计表';
CREATE TABLE IF NOT EXISTS user_mic_lifetime_stats (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
seat_occupied_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位占用毫秒值',
mic_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦位在线毫秒值',
session_count BIGINT NOT NULL DEFAULT 0 COMMENT '会话数量',
first_mic_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首次麦位时间UTC epoch ms',
last_mic_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后麦位时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id),
KEY idx_user_mic_lifetime_mic_online (app_code, mic_online_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户麦位累计统计表';
CREATE TABLE IF NOT EXISTS user_mic_event_consumption (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
mic_session_id VARCHAR(128) NOT NULL COMMENT '麦位会话 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
action VARCHAR(32) NOT NULL COMMENT '操作',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
consumed_at_ms BIGINT NULL COMMENT '消费时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, event_id),
KEY idx_user_mic_event_session (app_code, mic_session_id, created_at_ms),
KEY idx_user_mic_event_user (app_code, user_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户麦位事件消费位点表';
CREATE TABLE IF NOT EXISTS host_profiles (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
region_id BIGINT NOT NULL COMMENT '区域 ID',
current_agency_id BIGINT NULL COMMENT '当前公会 ID',
current_membership_id BIGINT NULL COMMENT '当前成员关系 ID',
source VARCHAR(64) NOT NULL COMMENT '来源',
first_became_host_at_ms BIGINT NOT NULL COMMENT '首次成为主播时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
KEY idx_host_profiles_region_status (app_code, region_id, status),
KEY idx_host_profiles_agency (app_code, current_agency_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播资料表';
CREATE TABLE IF NOT EXISTS bd_profiles (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID',
role VARCHAR(32) NOT NULL COMMENT '角色',
region_id BIGINT NOT NULL COMMENT '区域 ID',
parent_leader_user_id BIGINT NULL COMMENT '父级负责人用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_by_user_id BIGINT NOT NULL COMMENT '创建人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
KEY idx_bd_profiles_region_role (app_code, region_id, role, status),
KEY idx_bd_profiles_parent_leader (app_code, parent_leader_user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BD资料表';
CREATE TABLE IF NOT EXISTS bd_leader_profiles (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
created_by_user_id BIGINT NOT NULL COMMENT '创建人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
KEY idx_bd_leader_profiles_region_status (app_code, region_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BD Leader资料表';
CREATE TABLE IF NOT EXISTS coin_seller_profiles (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
merchant_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN_SELLER_COIN' COMMENT '商户资产类型',
contact_info VARCHAR(128) NOT NULL DEFAULT '' COMMENT '联系信息',
created_by_user_id BIGINT NOT NULL COMMENT '创建人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
KEY idx_coin_seller_profiles_status (app_code, status, updated_at_ms),
KEY idx_coin_seller_profiles_created_by (app_code, created_by_user_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='金币商户资料表';
CREATE TABLE IF NOT EXISTS agencies (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
agency_id BIGINT NOT NULL PRIMARY KEY COMMENT '公会 ID',
owner_user_id BIGINT NOT NULL COMMENT '房主用户 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
parent_bd_user_id BIGINT NOT NULL COMMENT '父级BD用户 ID',
name VARCHAR(128) NOT NULL COMMENT '名称',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
join_enabled BOOLEAN NOT NULL COMMENT '加入是否启用',
max_hosts INT NOT NULL COMMENT '最大主播',
created_by_user_id BIGINT NOT NULL COMMENT '创建人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
active_owner_user_id BIGINT GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN owner_user_id ELSE NULL END
) STORED COMMENT '启用房主用户 ID',
UNIQUE KEY uk_agencies_active_owner (app_code, active_owner_user_id),
KEY idx_agencies_region_status (app_code, region_id, status, join_enabled),
KEY idx_agencies_parent_bd (app_code, parent_bd_user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公会表';
CREATE TABLE IF NOT EXISTS agency_memberships (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
membership_id BIGINT NOT NULL PRIMARY KEY COMMENT '成员关系 ID',
agency_id BIGINT NOT NULL COMMENT '公会 ID',
host_user_id BIGINT NOT NULL COMMENT '主播用户 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
membership_type VARCHAR(32) NOT NULL COMMENT '成员关系类型',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
joined_at_ms BIGINT NOT NULL COMMENT '加入时间UTC epoch ms',
ended_at_ms BIGINT NULL COMMENT '结束时间UTC epoch ms',
ended_by_user_id BIGINT NULL COMMENT '结束操作用户 ID',
ended_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '结束原因',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
active_host_user_id BIGINT GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN host_user_id ELSE NULL END
) STORED COMMENT '启用主播用户 ID',
UNIQUE KEY uk_agency_memberships_active_host (app_code, active_host_user_id),
KEY idx_agency_memberships_agency_status (app_code, agency_id, status),
KEY idx_agency_memberships_host_status (app_code, host_user_id, status),
KEY idx_agency_memberships_effective (app_code, host_user_id, joined_at_ms, ended_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公会成员关系表';
CREATE TABLE IF NOT EXISTS agency_applications (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
application_id BIGINT NOT NULL PRIMARY KEY COMMENT '申请 ID',
command_id VARCHAR(96) NOT NULL COMMENT '业务命令幂等 ID',
applicant_user_id BIGINT NOT NULL COMMENT '申请人用户 ID',
agency_id BIGINT NOT NULL COMMENT '公会 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
reviewed_by_user_id BIGINT NULL COMMENT '审核用户 ID',
review_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '审核原因',
reviewed_at_ms BIGINT NULL COMMENT '审核时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
pending_applicant_user_id BIGINT GENERATED ALWAYS AS (
CASE WHEN status = 'pending' THEN applicant_user_id ELSE NULL END
) STORED COMMENT '待处理申请人用户 ID',
UNIQUE KEY uk_agency_applications_command (app_code, command_id),
UNIQUE KEY uk_agency_applications_pending_user (app_code, pending_applicant_user_id),
KEY idx_agency_applications_agency_status (app_code, agency_id, status, created_at_ms),
KEY idx_agency_applications_applicant_status (app_code, applicant_user_id, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公会申请表';
CREATE TABLE IF NOT EXISTS role_invitations (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
invitation_id BIGINT NOT NULL PRIMARY KEY COMMENT '邀请 ID',
command_id VARCHAR(96) NOT NULL COMMENT '业务命令幂等 ID',
invitation_type VARCHAR(32) NOT NULL COMMENT '邀请类型',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
inviter_user_id BIGINT NOT NULL COMMENT '邀请人用户 ID',
inviter_bd_user_id BIGINT NOT NULL COMMENT '邀请人BD用户 ID',
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
region_id BIGINT NOT NULL COMMENT '区域 ID',
agency_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '公会名称',
parent_bd_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '父级BD用户 ID',
parent_leader_user_id BIGINT NULL COMMENT '父级负责人用户 ID',
processed_by_user_id BIGINT NULL COMMENT '处理用户 ID',
process_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '处理原因',
processed_at_ms BIGINT NULL COMMENT '处理时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
pending_target_key VARCHAR(128) GENERATED ALWAYS AS (
CASE WHEN status = 'pending' THEN CONCAT(invitation_type, ':', target_user_id) ELSE NULL END
) STORED COMMENT '待处理目标键',
UNIQUE KEY uk_role_invitations_command (app_code, command_id),
UNIQUE KEY uk_role_invitations_pending_target (app_code, pending_target_key),
KEY idx_role_invitations_target_status (app_code, target_user_id, status, created_at_ms),
KEY idx_role_invitations_inviter_status (app_code, inviter_user_id, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色邀请表';
CREATE TABLE IF NOT EXISTS host_command_results (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
command_id VARCHAR(96) NOT NULL PRIMARY KEY COMMENT '业务命令幂等 ID',
command_type VARCHAR(64) NOT NULL COMMENT '命令类型',
result_type VARCHAR(64) NOT NULL COMMENT '结果类型',
result_id BIGINT NOT NULL COMMENT '结果 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
KEY idx_host_command_results_result (app_code, result_type, result_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播命令结果表';
CREATE TABLE IF NOT EXISTS host_outbox (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
event_id BIGINT NOT NULL PRIMARY KEY COMMENT '事件幂等 ID',
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型',
aggregate_id VARCHAR(96) NOT NULL COMMENT '聚合 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
payload_json JSON NOT NULL COMMENT '业务负载 JSON 快照',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最后一次失败原因',
KEY idx_host_outbox_status_created (app_code, status, created_at_ms),
KEY idx_host_outbox_aggregate (app_code, aggregate_type, aggregate_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播发件箱表';
-- 国家种子由 services/user-service/deploy/data/countries.json 生成,避免 SQL 与数据源分叉。
-- 区域种子使用产品定义的业务分区,不按原始地理来源自动推断。
INSERT INTO countries (country_name, country_code, iso_alpha3, iso_numeric, country_display_name, phone_country_code, flag, enabled, sort_order, created_at_ms, updated_at_ms) VALUES
('United Arab Emirates', 'AE', 'ARE', '784', '阿拉伯联合酋长国', '+971', '🇦🇪', TRUE, 20, 0, 0),
('Afghanistan', 'AF', 'AFG', '004', '阿富汗', '+93', '🇦🇫', TRUE, 30, 0, 0),
('Albania', 'AL', 'ALB', '008', '阿尔巴尼亚', '+355', '🇦🇱', TRUE, 60, 0, 0),
('Armenia', 'AM', 'ARM', '051', '亚美尼亚', '+374', '🇦🇲', TRUE, 70, 0, 0),
('Angola', 'AO', 'AGO', '024', '安哥拉', '+244', '🇦🇴', TRUE, 80, 0, 0),
('Argentina', 'AR', 'ARG', '032', '阿根廷', '+54', '🇦🇷', TRUE, 100, 0, 0),
('Austria', 'AT', 'AUT', '040', '奥地利', '+43', '🇦🇹', TRUE, 120, 0, 0),
('Australia', 'AU', 'AUS', '036', '澳大利亚', '+61', '🇦🇺', TRUE, 130, 0, 0),
('Bangladesh', 'BD', 'BGD', '050', '孟加拉国', '+880', '🇧🇩', TRUE, 190, 0, 0),
('Belgium', 'BE', 'BEL', '056', '比利时', '+32', '🇧🇪', TRUE, 200, 0, 0),
('Bulgaria', 'BG', 'BGR', '100', '保加利亚', '+359', '🇧🇬', TRUE, 220, 0, 0),
('Bahrain', 'BH', 'BHR', '048', '巴林', '+973', '🇧🇭', TRUE, 230, 0, 0),
('Benin', 'BJ', 'BEN', '204', '贝宁', '+229', '🇧🇯', TRUE, 250, 0, 0),
('Bolivia', 'BO', 'BOL', '068', '玻利维亚', '+591', '🇧🇴', TRUE, 290, 0, 0),
('Brazil', 'BR', 'BRA', '076', '巴西', '+55', '🇧🇷', TRUE, 310, 0, 0),
('Botswana', 'BW', 'BWA', '072', '博茨瓦纳', '+267', '🇧🇼', TRUE, 350, 0, 0),
('Belarus', 'BY', 'BLR', '112', '白俄罗斯', '+375', '🇧🇾', TRUE, 360, 0, 0),
('Canada', 'CA', 'CAN', '124', '加拿大', '+1', '🇨🇦', TRUE, 380, 0, 0),
('DR Congo', 'CD', 'COD', '180', '民主刚果', '+243', '🇨🇩', TRUE, 400, 0, 0),
('Central African Republic', 'CF', 'CAF', '140', '中非共和国', '+236', '🇨🇫', TRUE, 410, 0, 0),
('Congo', 'CG', 'COG', '178', '刚果', '+242', '🇨🇬', TRUE, 420, 0, 0),
('Switzerland', 'CH', 'CHE', '756', '瑞士', '+41', '🇨🇭', TRUE, 430, 0, 0),
('Ivory Coast', 'CI', 'CIV', '384', '科特迪瓦', '+225', '🇨🇮', TRUE, 440, 0, 0),
('Chile', 'CL', 'CHL', '152', '智利', '+56', '🇨🇱', TRUE, 460, 0, 0),
('Cameroon', 'CM', 'CMR', '120', '喀麦隆', '+237', '🇨🇲', TRUE, 470, 0, 0),
('Colombia', 'CO', 'COL', '170', '哥伦比亚', '+57', '🇨🇴', TRUE, 490, 0, 0),
('Costa Rica', 'CR', 'CRI', '188', '哥斯达黎加', '+506', '🇨🇷', TRUE, 500, 0, 0),
('Cuba', 'CU', 'CUB', '192', '古巴', '+53', '🇨🇺', TRUE, 510, 0, 0),
('Cyprus', 'CY', 'CYP', '196', '塞浦路斯', '+357', '🇨🇾', TRUE, 550, 0, 0),
('Czechia', 'CZ', 'CZE', '203', '捷克', '+420', '🇨🇿', TRUE, 560, 0, 0),
('Germany', 'DE', 'DEU', '276', '德国', '+49', '🇩🇪', TRUE, 570, 0, 0),
('Djibouti', 'DJ', 'DJI', '262', '吉布提', '+253', '🇩🇯', TRUE, 580, 0, 0),
('Denmark', 'DK', 'DNK', '208', '丹麦', '+45', '🇩🇰', TRUE, 590, 0, 0),
('Dominican Republic', 'DO', 'DOM', '214', '多明尼加', '+1', '🇩🇴', TRUE, 610, 0, 0),
('Algeria', 'DZ', 'DZA', '012', '阿尔及利亚', '+213', '🇩🇿', TRUE, 620, 0, 0),
('Ecuador', 'EC', 'ECU', '218', '厄瓜多尔', '+593', '🇪🇨', TRUE, 630, 0, 0),
('Estonia', 'EE', 'EST', '233', '爱沙尼亚', '+372', '🇪🇪', TRUE, 640, 0, 0),
('Egypt', 'EG', 'EGY', '818', '埃及', '+20', '🇪🇬', TRUE, 650, 0, 0),
('Eritrea', 'ER', 'ERI', '232', '厄立特里亚', '+291', '🇪🇷', TRUE, 670, 0, 0),
('Spain', 'ES', 'ESP', '724', '西班牙', '+34', '🇪🇸', TRUE, 680, 0, 0),
('Ethiopia', 'ET', 'ETH', '231', '埃塞俄比亚', '+251', '🇪🇹', TRUE, 690, 0, 0),
('Finland', 'FI', 'FIN', '246', '芬兰', '+358', '🇫🇮', TRUE, 700, 0, 0),
('France', 'FR', 'FRA', '250', '法国', '+33', '🇫🇷', TRUE, 750, 0, 0),
('Gabon', 'GA', 'GAB', '266', '加蓬', '+241', '🇬🇦', TRUE, 760, 0, 0),
('United Kingdom', 'GB', 'GBR', '826', '英国', '+44', '🇬🇧', TRUE, 770, 0, 0),
('Georgia', 'GE', 'GEO', '268', '格鲁吉亚', '+995', '🇬🇪', TRUE, 790, 0, 0),
('Ghana', 'GH', 'GHA', '288', '加纳', '+233', '🇬🇭', TRUE, 820, 0, 0),
('Gambia', 'GM', 'GMB', '270', '冈比亚', '+220', '🇬🇲', TRUE, 850, 0, 0),
('Guinea', 'GN', 'GIN', '324', '几内亚', '+224', '🇬🇳', TRUE, 860, 0, 0),
('Equatorial Guinea', 'GQ', 'GNQ', '226', '赤道几内亚', '+240', '🇬🇶', TRUE, 880, 0, 0),
('Greece', 'GR', 'GRC', '300', '希腊', '+30', '🇬🇷', TRUE, 890, 0, 0),
('Guatemala', 'GT', 'GTM', '320', '危地马拉', '+502', '🇬🇹', TRUE, 910, 0, 0),
('Honduras', 'HN', 'HND', '340', '洪都拉斯', '+504', '🇭🇳', TRUE, 970, 0, 0),
('Croatia', 'HR', 'HRV', '191', '克罗地亚', '+385', '🇭🇷', TRUE, 980, 0, 0),
('Haiti', 'HT', 'HTI', '332', '海地', '+509', '🇭🇹', TRUE, 990, 0, 0),
('Hungary', 'HU', 'HUN', '348', '匈牙利', '+36', '🇭🇺', TRUE, 1000, 0, 0),
('Indonesia', 'ID', 'IDN', '360', '印度尼西亚', '+62', '🇮🇩', TRUE, 1010, 0, 0),
('Ireland', 'IE', 'IRL', '372', '爱尔兰', '+353', '🇮🇪', TRUE, 1020, 0, 0),
('Israel', 'IL', 'ISR', '376', '以色列', '+972', '🇮🇱', TRUE, 1030, 0, 0),
('India', 'IN', 'IND', '356', '印度', '+91', '🇮🇳', TRUE, 1050, 0, 0),
('Iraq', 'IQ', 'IRQ', '368', '伊拉克', '+964', '🇮🇶', TRUE, 1070, 0, 0),
('Iran', 'IR', 'IRN', '364', '伊朗', '+98', '🇮🇷', TRUE, 1080, 0, 0),
('Italy', 'IT', 'ITA', '380', '意大利', '+39', '🇮🇹', TRUE, 1100, 0, 0),
('Jamaica', 'JM', 'JAM', '388', '牙买加', '+1', '🇯🇲', TRUE, 1120, 0, 0),
('Jordan', 'JO', 'JOR', '400', '约旦', '+962', '🇯🇴', TRUE, 1130, 0, 0),
('Japan', 'JP', 'JPN', '392', '日本', '+81', '🇯🇵', TRUE, 1140, 0, 0),
('Kenya', 'KE', 'KEN', '404', '肯尼亚', '+254', '🇰🇪', TRUE, 1150, 0, 0),
('Kyrgyzstan', 'KG', 'KGZ', '417', '吉尔吉斯斯坦', '+996', '🇰🇬', TRUE, 1160, 0, 0),
('Cambodia', 'KH', 'KHM', '116', '柬埔寨', '+855', '🇰🇭', TRUE, 1170, 0, 0),
('North Korea', 'KP', 'PRK', '408', '朝鲜', '+850', '🇰🇵', TRUE, 1210, 0, 0),
('South Korea', 'KR', 'KOR', '410', '韩国', '+82', '🇰🇷', TRUE, 1220, 0, 0),
('Kuwait', 'KW', 'KWT', '414', '科威特', '+965', '🇰🇼', TRUE, 1230, 0, 0),
('Kazakhstan', 'KZ', 'KAZ', '398', '哈萨克斯坦', '+7', '🇰🇿', TRUE, 1250, 0, 0),
('Laos', 'LA', 'LAO', '418', '老挝', '+856', '🇱🇦', TRUE, 1260, 0, 0),
('Lebanon', 'LB', 'LBN', '422', '黎巴嫩', '+961', '🇱🇧', TRUE, 1270, 0, 0),
('Sri Lanka', 'LK', 'LKA', '144', '斯里兰卡', '+94', '🇱🇰', TRUE, 1300, 0, 0),
('Liberia', 'LR', 'LBR', '430', '利比里亚', '+231', '🇱🇷', TRUE, 1310, 0, 0),
('Libya', 'LY', 'LBY', '434', '利比亚', '+218', '🇱🇾', TRUE, 1360, 0, 0),
('Morocco', 'MA', 'MAR', '504', '摩洛哥', '+212', '🇲🇦', TRUE, 1370, 0, 0),
('Madagascar', 'MG', 'MDG', '450', '马达加斯加', '+261', '🇲🇬', TRUE, 1420, 0, 0),
('Mali', 'ML', 'MLI', '466', '马里', '+223', '🇲🇱', TRUE, 1450, 0, 0),
('Myanmar', 'MM', 'MMR', '104', '缅甸', '+95', '🇲🇲', TRUE, 1460, 0, 0),
('Mongolia', 'MN', 'MNG', '496', '蒙古', '+976', '🇲🇳', TRUE, 1470, 0, 0),
('Mauritius', 'MU', 'MUS', '480', '毛里求斯', '+230', '🇲🇺', TRUE, 1540, 0, 0),
('Maldives', 'MV', 'MDV', '462', '马尔代夫', '+960', '🇲🇻', TRUE, 1550, 0, 0),
('Mexico', 'MX', 'MEX', '484', '墨西哥', '+52', '🇲🇽', TRUE, 1570, 0, 0),
('Malaysia', 'MY', 'MYS', '458', '马来西亚', '+60', '🇲🇾', TRUE, 1580, 0, 0),
('Mozambique', 'MZ', 'MOZ', '508', '莫桑比克', '+258', '🇲🇿', TRUE, 1590, 0, 0),
('Namibia', 'NA', 'NAM', '516', '纳米比亚', '+264', '🇳🇦', TRUE, 1600, 0, 0),
('Niger', 'NE', 'NER', '562', '尼日尔', '+227', '🇳🇪', TRUE, 1620, 0, 0),
('Nigeria', 'NG', 'NGA', '566', '尼日利亚', '+234', '🇳🇬', TRUE, 1640, 0, 0),
('Nicaragua', 'NI', 'NIC', '558', '尼加拉瓜', '+505', '🇳🇮', TRUE, 1650, 0, 0),
('Netherlands', 'NL', 'NLD', '528', '荷兰', '+31', '🇳🇱', TRUE, 1660, 0, 0),
('Norway', 'NO', 'NOR', '578', '挪威', '+47', '🇳🇴', TRUE, 1670, 0, 0),
('Nepal', 'NP', 'NPL', '524', '尼泊尔', '+977', '🇳🇵', TRUE, 1680, 0, 0),
('New Zealand', 'NZ', 'NZL', '554', '新西兰', '+64', '🇳🇿', TRUE, 1710, 0, 0),
('Oman', 'OM', 'OMN', '512', '阿曼', '+968', '🇴🇲', TRUE, 1720, 0, 0),
('Panama', 'PA', 'PAN', '591', '巴拿马', '+507', '🇵🇦', TRUE, 1730, 0, 0),
('Peru', 'PE', 'PER', '604', '秘鲁', '+51', '🇵🇪', TRUE, 1740, 0, 0),
('Philippines', 'PH', 'PHL', '608', '菲律宾', '+63', '🇵🇭', TRUE, 1770, 0, 0),
('Pakistan', 'PK', 'PAK', '586', '巴基斯坦', '+92', '🇵🇰', TRUE, 1780, 0, 0),
('Poland', 'PL', 'POL', '616', '波兰', '+48', '🇵🇱', TRUE, 1790, 0, 0),
('Puerto Rico', 'PR', 'PRI', '630', '波多黎各', '+1', '🇵🇷', TRUE, 1820, 0, 0),
('Palestine', 'PS', 'PSE', '275', '巴勒斯坦', '+970', '🇵🇸', TRUE, 1830, 0, 0),
('Portugal', 'PT', 'PRT', '620', '葡萄牙', '+351', '🇵🇹', TRUE, 1840, 0, 0),
('Paraguay', 'PY', 'PRY', '600', '巴拉圭', '+595', '🇵🇾', TRUE, 1860, 0, 0),
('Qatar', 'QA', 'QAT', '634', '卡塔尔', '+974', '🇶🇦', TRUE, 1870, 0, 0),
('Serbia', 'RS', 'SRB', '688', '塞尔维亚', '+381', '🇷🇸', TRUE, 1900, 0, 0),
('Russia', 'RU', 'RUS', '643', '俄罗斯', '+7', '🇷🇺', TRUE, 1910, 0, 0),
('Rwanda', 'RW', 'RWA', '646', '卢旺达', '+250', '🇷🇼', TRUE, 1920, 0, 0),
('Saudi Arabia', 'SA', 'SAU', '682', '沙特阿拉伯', '+966', '🇸🇦', TRUE, 1930, 0, 0),
('Sudan', 'SD', 'SDN', '729', '苏丹', '+249', '🇸🇩', TRUE, 1960, 0, 0),
('Sweden', 'SE', 'SWE', '752', '瑞典', '+46', '🇸🇪', TRUE, 1970, 0, 0),
('Singapore', 'SG', 'SGP', '702', '新加坡', '+65', '🇸🇬', TRUE, 1980, 0, 0),
('Slovakia', 'SK', 'SVK', '703', '斯洛伐克', '+421', '🇸🇰', TRUE, 2020, 0, 0),
('Sierra Leone', 'SL', 'SLE', '694', '塞拉利昂', '+232', '🇸🇱', TRUE, 2030, 0, 0),
('Senegal', 'SN', 'SEN', '686', '塞内加尔', '+221', '🇸🇳', TRUE, 2050, 0, 0),
('Somalia', 'SO', 'SOM', '706', '索马里', '+252', '🇸🇴', TRUE, 2060, 0, 0),
('South Sudan', 'SS', 'SSD', '728', '南苏丹', '+211', '🇸🇸', TRUE, 2080, 0, 0),
('El Salvador', 'SV', 'SLV', '222', '萨尔瓦多', '+503', '🇸🇻', TRUE, 2100, 0, 0),
('Syria', 'SY', 'SYR', '760', '叙利亚', '+963', '🇸🇾', TRUE, 2120, 0, 0),
('Eswatini', 'SZ', 'SWZ', '748', '斯威士兰', '+268', '🇸🇿', TRUE, 2130, 0, 0),
('Chad', 'TD', 'TCD', '148', '乍得', '+235', '🇹🇩', TRUE, 2150, 0, 0),
('Thailand', 'TH', 'THA', '764', '泰国', '+66', '🇹🇭', TRUE, 2180, 0, 0),
('Tajikistan', 'TJ', 'TJK', '762', '塔吉克斯坦', '+992', '🇹🇯', TRUE, 2190, 0, 0),
('Turkmenistan', 'TM', 'TKM', '795', '土库曼斯坦', '+993', '🇹🇲', TRUE, 2220, 0, 0),
('Tunisia', 'TN', 'TUN', '788', '突尼斯', '+216', '🇹🇳', TRUE, 2230, 0, 0),
('Türkiye', 'TR', 'TUR', '792', '土耳其', '+90', '🇹🇷', TRUE, 2250, 0, 0),
('Tanzania', 'TZ', 'TZA', '834', '坦桑尼亚', '+255', '🇹🇿', TRUE, 2290, 0, 0),
('Ukraine', 'UA', 'UKR', '804', '乌克兰', '+380', '🇺🇦', TRUE, 2300, 0, 0),
('Uganda', 'UG', 'UGA', '800', '乌干达', '+256', '🇺🇬', TRUE, 2310, 0, 0),
('United States', 'US', 'USA', '840', '美国', '+1', '🇺🇸', TRUE, 2330, 0, 0),
('Uruguay', 'UY', 'URY', '858', '乌拉圭', '+598', '🇺🇾', TRUE, 2340, 0, 0),
('Uzbekistan', 'UZ', 'UZB', '860', '乌兹别克斯坦', '+998', '🇺🇿', TRUE, 2350, 0, 0),
('Venezuela', 'VE', 'VEN', '862', '委内瑞拉', '+58', '🇻🇪', TRUE, 2380, 0, 0),
('Vietnam', 'VN', 'VNM', '704', '越南', '+84', '🇻🇳', TRUE, 2410, 0, 0),
('Kosovo', 'XK', 'UNK', NULL, '科索沃', '+383', '🇽🇰', TRUE, 2450, 0, 0),
('Yemen', 'YE', 'YEM', '887', '也门', '+967', '🇾🇪', TRUE, 2460, 0, 0),
('Zambia', 'ZM', 'ZMB', '894', '赞比亚', '+260', '🇿🇲', TRUE, 2490, 0, 0),
('Zimbabwe', 'ZW', 'ZWE', '716', '津巴布韦', '+263', '🇿🇼', TRUE, 2500, 0, 0)
ON DUPLICATE KEY UPDATE
country_name = VALUES(country_name),
iso_alpha3 = VALUES(iso_alpha3),
iso_numeric = VALUES(iso_numeric),
country_display_name = VALUES(country_display_name),
phone_country_code = VALUES(phone_country_code),
flag = VALUES(flag),
enabled = VALUES(enabled),
sort_order = VALUES(sort_order),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO regions (region_code, name, status, sort_order, created_at_ms, updated_at_ms) VALUES
('MIDDLE_EAST', '中东区', 'active', 10, 0, 0),
('INDIA', '印度区', 'active', 20, 0, 0),
('EURASIA_AMERICA', '欧亚美区', 'active', 30, 0, 0)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
status = VALUES(status),
sort_order = VALUES(sort_order),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO region_countries (app_code, region_id, country_code, status, created_at_ms, updated_at_ms)
SELECT 'lalu', r.region_id, seed.country_code, 'active', 0, 0
FROM (
SELECT 'AE' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'AF' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'AL' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'AM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'AO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'AR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'AT' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'AU' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BD' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'BE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BH' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'BJ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BW' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'BY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CD' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CF' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CH' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CI' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CL' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CU' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'CZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'DE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'DJ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'DK' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'DO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'DZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'EC' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'EE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'EG' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'ER' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'ES' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'ET' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'FI' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'FR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GB' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GH' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GQ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'GT' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'HN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'HR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'HT' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'HU' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'ID' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'IE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'IL' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'IN' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'IQ' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'IR' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'IT' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'JM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'JO' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'JP' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KH' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KP' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'KW' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'KZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'LA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'LB' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'LK' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'LR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'LY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'ML' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MU' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MV' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'MX' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'MZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NI' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NL' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'NP' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'NZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'OM' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'PA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PH' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PK' AS country_code, 'INDIA' AS region_code
UNION ALL
SELECT 'PL' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PR' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PS' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'PT' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'PY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'QA' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'RS' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'RU' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'RW' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SA' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'SD' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SK' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SL' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SO' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SS' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SV' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'SY' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'SZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TD' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TH' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TJ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'TR' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'TZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'UA' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'UG' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'US' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'UY' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'UZ' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'VE' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'VN' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'XK' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'YE' AS country_code, 'MIDDLE_EAST' AS region_code
UNION ALL
SELECT 'ZM' AS country_code, 'EURASIA_AMERICA' AS region_code
UNION ALL
SELECT 'ZW' AS country_code, 'EURASIA_AMERICA' AS region_code
) AS seed
INNER JOIN regions r ON r.app_code = 'lalu' AND r.region_code = seed.region_code
INNER JOIN countries c ON c.app_code = 'lalu' AND c.country_code = seed.country_code
ON DUPLICATE KEY UPDATE
region_id = VALUES(region_id),
status = VALUES(status),
updated_at_ms = VALUES(updated_at_ms);
-- 区域管理只暴露产品定义的业务分区GLOBAL 仅作为内部兜底,不作为后台可管理区域。
DELETE FROM regions
WHERE app_code = 'lalu'
AND region_code NOT IN ('MIDDLE_EAST', 'INDIA', 'EURASIA_AMERICA');
-- 产品明确排除的国家直接硬删除,保证重复导入 initdb 时新旧本地库都能对齐当前国家主数据。
DELETE FROM region_countries
WHERE app_code = 'lalu'
AND country_code IN ('AD', 'AG', 'AI', 'AQ', 'AS', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BF', 'BI', 'BL', 'BM', 'BN', 'BQ', 'BS', 'BT', 'BV', 'BZ', 'CC', 'CK', 'CN', 'CV', 'CW', 'CX', 'DM', 'EH', 'FJ', 'FK', 'FM', 'FO', 'GD', 'GF', 'GG', 'GI', 'GL', 'GP', 'GS', 'GU', 'GW', 'GY', 'HK', 'HM', 'IM', 'IO', 'IS', 'JE', 'KI', 'KM', 'KN', 'KY', 'LC', 'LI', 'LS', 'LT', 'LU', 'LV', 'MC', 'MD', 'ME', 'MF', 'MH', 'MK', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MW', 'NC', 'NF', 'NR', 'NU', 'PF', 'PG', 'PM', 'PN', 'PW', 'RE', 'RO', 'SB', 'SC', 'SH', 'SI', 'SJ', 'SM', 'SR', 'ST', 'SX', 'TC', 'TF', 'TG', 'TK', 'TL', 'TO', 'TT', 'TV', 'TW', 'UM', 'VA', 'VC', 'VG', 'VI', 'VU', 'WF', 'WS', 'YT', 'ZA');
DELETE FROM countries
WHERE app_code = 'lalu'
AND country_code IN ('AD', 'AG', 'AI', 'AQ', 'AS', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BF', 'BI', 'BL', 'BM', 'BN', 'BQ', 'BS', 'BT', 'BV', 'BZ', 'CC', 'CK', 'CN', 'CV', 'CW', 'CX', 'DM', 'EH', 'FJ', 'FK', 'FM', 'FO', 'GD', 'GF', 'GG', 'GI', 'GL', 'GP', 'GS', 'GU', 'GW', 'GY', 'HK', 'HM', 'IM', 'IO', 'IS', 'JE', 'KI', 'KM', 'KN', 'KY', 'LC', 'LI', 'LS', 'LT', 'LU', 'LV', 'MC', 'MD', 'ME', 'MF', 'MH', 'MK', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MW', 'NC', 'NF', 'NR', 'NU', 'PF', 'PG', 'PM', 'PN', 'PW', 'RE', 'RO', 'SB', 'SC', 'SH', 'SI', 'SJ', 'SM', 'SR', 'ST', 'SX', 'TC', 'TF', 'TG', 'TK', 'TL', 'TO', 'TT', 'TV', 'TW', 'UM', 'VA', 'VC', 'VG', 'VI', 'VU', 'WF', 'WS', 'YT', 'ZA');
CREATE TABLE IF NOT EXISTS user_display_user_ids (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
display_user_id VARCHAR(32) NOT NULL COMMENT '展示用户 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
display_user_id_kind VARCHAR(32) NOT NULL COMMENT '展示用户 ID分类',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
assigned_at_ms BIGINT NOT NULL COMMENT '分配时间UTC epoch ms',
activated_at_ms BIGINT NULL COMMENT '激活时间UTC epoch ms',
expires_at_ms BIGINT NULL COMMENT '过期时间UTC epoch ms',
released_at_ms BIGINT NULL COMMENT '释放时间UTC epoch ms',
release_reason VARCHAR(64) NULL COMMENT '释放原因',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
live_display_user_id VARCHAR(32)
GENERATED ALWAYS AS (
CASE
WHEN status IN ('active', 'held', 'reserved', 'blocked') THEN display_user_id
ELSE NULL
END
) STORED COMMENT '实时展示用户 ID',
active_user_id BIGINT
GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN user_id ELSE NULL END
) STORED COMMENT '启用用户 ID',
UNIQUE KEY uk_user_display_user_ids_live (app_code, live_display_user_id),
UNIQUE KEY uk_user_display_user_ids_active_user (app_code, active_user_id),
KEY idx_user_display_user_ids_user_id (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户展示 ID 表';
CREATE TABLE IF NOT EXISTS pretty_display_user_id_leases (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
lease_id VARCHAR(64) NOT NULL PRIMARY KEY COMMENT '租约 ID',
display_user_id VARCHAR(32) NOT NULL COMMENT '展示用户 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
starts_at_ms BIGINT NOT NULL COMMENT '开始时间UTC epoch ms',
expires_at_ms BIGINT NOT NULL COMMENT '过期时间UTC epoch ms',
payment_receipt_id VARCHAR(64) NULL COMMENT '支付凭据 ID',
source VARCHAR(32) NOT NULL COMMENT '来源',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
active_display_user_id VARCHAR(32)
GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN display_user_id ELSE NULL END
) STORED COMMENT '启用展示用户 ID',
active_user_id BIGINT
GENERATED ALWAYS AS (
CASE WHEN status = 'active' THEN user_id ELSE NULL END
) STORED COMMENT '启用用户 ID',
UNIQUE KEY uk_pretty_display_user_id_active (app_code, active_display_user_id),
UNIQUE KEY uk_pretty_display_user_id_active_user (app_code, active_user_id),
KEY idx_pretty_display_user_id_leases_user (app_code, user_id, status),
KEY idx_pretty_display_user_id_leases_expire (app_code, status, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='靓号展示用户 ID 租约表';
CREATE TABLE IF NOT EXISTS display_user_id_change_logs (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
old_display_user_id VARCHAR(32) NOT NULL COMMENT '原展示用户 ID',
new_display_user_id VARCHAR(32) NOT NULL COMMENT '新展示用户 ID',
old_display_user_id_kind VARCHAR(32) NOT NULL COMMENT '原展示用户 ID分类',
new_display_user_id_kind VARCHAR(32) NOT NULL COMMENT '新展示用户 ID分类',
change_type VARCHAR(32) NOT NULL COMMENT '变更类型',
lease_id VARCHAR(64) NULL COMMENT '租约 ID',
reason VARCHAR(64) NOT NULL COMMENT '原因',
operator_user_id BIGINT NULL COMMENT '操作人用户 ID',
request_id VARCHAR(96) NOT NULL COMMENT '链路请求 ID用于排查问题',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
KEY idx_display_user_id_change_logs_user_id (app_code, user_id),
KEY idx_display_user_id_change_logs_request_id (app_code, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='展示用户 ID变更日志表';
CREATE TABLE IF NOT EXISTS user_country_change_logs (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
old_country VARCHAR(64) NULL COMMENT '原国家',
new_country VARCHAR(64) NOT NULL COMMENT '新国家',
request_id VARCHAR(96) NOT NULL COMMENT '链路请求 ID用于排查问题',
changed_at_ms BIGINT NOT NULL COMMENT '变更时间UTC epoch ms',
KEY idx_user_country_change_logs_user_changed (app_code, user_id, changed_at_ms),
KEY idx_user_country_change_logs_request_id (app_code, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户国家变更日志表';
CREATE TABLE IF NOT EXISTS password_accounts (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
user_id BIGINT NOT NULL COMMENT '用户 ID',
password_hash VARCHAR(255) NOT NULL COMMENT '密码哈希值',
hash_alg VARCHAR(32) NOT NULL COMMENT '哈希算法',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='密码账户表';
CREATE TABLE IF NOT EXISTS third_party_identities (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
provider VARCHAR(64) NOT NULL COMMENT '提供方',
provider_subject VARCHAR(191) NOT NULL COMMENT '提供方主体',
provider_union_id VARCHAR(191) NULL COMMENT '提供方联合 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_third_party_provider_subject (app_code, provider, provider_subject),
KEY idx_third_party_user_id (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='第三方身份表';
CREATE TABLE IF NOT EXISTS auth_sessions (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
session_id VARCHAR(96) NOT NULL PRIMARY KEY COMMENT '会话 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
refresh_token_hash VARCHAR(128) NOT NULL COMMENT '刷新令牌哈希值',
device_id VARCHAR(128) NOT NULL COMMENT '设备 ID',
expires_at_ms BIGINT NOT NULL COMMENT '过期时间UTC epoch ms',
last_heartbeat_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最近 App 心跳时间UTC epoch ms',
last_heartbeat_request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '最近 App 心跳请求 ID',
revoked_at_ms BIGINT NULL COMMENT '吊销时间UTC epoch ms',
revoked_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '吊销原因',
revoked_request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '吊销请求 ID',
revoked_by VARCHAR(64) NOT NULL DEFAULT '' COMMENT '吊销操作方',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
UNIQUE KEY uk_auth_sessions_refresh_token_hash (app_code, refresh_token_hash),
KEY idx_auth_sessions_user_id (app_code, user_id),
KEY idx_auth_sessions_heartbeat (app_code, last_heartbeat_at_ms),
KEY idx_auth_sessions_expires_at (app_code, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='认证会话表';
-- 老环境已经存在 auth_sessions 时CREATE TABLE IF NOT EXISTS 不会补 App 心跳字段。
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'last_heartbeat_at_ms') = 0,
'ALTER TABLE auth_sessions ADD COLUMN last_heartbeat_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''最近 App 心跳时间UTC epoch ms'' AFTER expires_at_ms',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'last_heartbeat_request_id') = 0,
'ALTER TABLE auth_sessions ADD COLUMN last_heartbeat_request_id VARCHAR(96) NOT NULL DEFAULT '''' COMMENT ''最近 App 心跳请求 ID'' AFTER last_heartbeat_at_ms',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl := IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND INDEX_NAME = 'idx_auth_sessions_heartbeat') = 0,
'ALTER TABLE auth_sessions ADD INDEX idx_auth_sessions_heartbeat (app_code, last_heartbeat_at_ms)',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
CREATE TABLE IF NOT EXISTS login_audit (
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
request_id VARCHAR(96) NOT NULL COMMENT '链路请求 ID用于排查问题',
user_id BIGINT NULL COMMENT '用户 ID',
login_type VARCHAR(32) NOT NULL COMMENT '登录类型',
provider VARCHAR(64) NULL COMMENT '提供方',
channel VARCHAR(32) NOT NULL DEFAULT '' COMMENT '渠道',
platform VARCHAR(16) NOT NULL DEFAULT '' COMMENT '平台',
result VARCHAR(32) NOT NULL COMMENT '结果',
failure_code VARCHAR(64) NULL COMMENT '失败编码',
client_ip VARCHAR(64) NULL COMMENT '客户端IP',
ip_country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT 'IP国家编码',
blocked TINYINT(1) NOT NULL DEFAULT 0 COMMENT '已拦截',
block_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '拦截原因',
user_agent VARCHAR(512) NULL COMMENT '用户代理',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
KEY idx_login_audit_user_id (app_code, user_id),
KEY idx_login_audit_request_id (app_code, request_id),
KEY idx_login_audit_created_at (app_code, created_at_ms),
KEY idx_login_audit_user_created (app_code, user_id, created_at_ms),
KEY idx_login_audit_blocked (app_code, blocked, created_at_ms),
KEY idx_login_audit_ip_country (app_code, ip_country_code, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录审计表';
CREATE TABLE IF NOT EXISTS login_ip_risk_jobs (
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
job_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
session_id VARCHAR(96) NOT NULL COMMENT '会话 ID',
user_id BIGINT NOT NULL COMMENT '用户 ID',
client_ip VARCHAR(64) NOT NULL COMMENT '客户端IP',
client_ip_hash VARCHAR(128) NOT NULL COMMENT '客户端IP哈希值',
channel VARCHAR(32) NOT NULL COMMENT '渠道',
platform VARCHAR(16) NOT NULL COMMENT '平台',
language VARCHAR(32) NOT NULL DEFAULT '' COMMENT '语言',
timezone VARCHAR(64) NOT NULL DEFAULT '' COMMENT '时区',
request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '链路请求 ID用于排查问题',
edge_country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT '边缘国家编码',
status VARCHAR(32) NOT NULL COMMENT '业务状态',
decision VARCHAR(32) NOT NULL DEFAULT '' COMMENT '决策',
country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT '国家或地区编码',
failure_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '失败原因',
locked_by VARCHAR(128) NULL COMMENT '当前锁定 worker',
locked_until_ms BIGINT NULL COMMENT '锁定截止时间UTC epoch ms',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (app_code, job_id),
KEY idx_login_ip_risk_jobs_status (app_code, status, updated_at_ms),
KEY idx_login_ip_risk_jobs_session (app_code, session_id),
KEY idx_login_ip_risk_jobs_user (app_code, user_id, created_at_ms),
KEY idx_login_ip_risk_jobs_ip (app_code, client_ip_hash, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录 IP风险任务表';
CREATE TABLE IF NOT EXISTS login_ip_risk_decisions (
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
decision_id VARCHAR(96) NOT NULL COMMENT '决策 ID',
client_ip VARCHAR(64) NOT NULL COMMENT '客户端IP',
client_ip_hash VARCHAR(128) NOT NULL COMMENT '客户端IP哈希值',
decision VARCHAR(32) NOT NULL COMMENT '决策',
country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT '国家或地区编码',
confidence INT NOT NULL DEFAULT 0 COMMENT '置信度',
provider_attempts_json JSON NOT NULL COMMENT '提供方尝试记录 JSON 配置或快照',
decided_at_ms BIGINT NOT NULL COMMENT '决策时间UTC epoch ms',
expires_at_ms BIGINT NOT NULL COMMENT '过期时间UTC epoch ms',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
PRIMARY KEY (app_code, decision_id),
KEY idx_login_ip_risk_decisions_ip (app_code, client_ip_hash, decided_at_ms),
KEY idx_login_ip_risk_decisions_country (app_code, country_code, decided_at_ms),
KEY idx_login_ip_risk_decisions_expires (app_code, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录 IP风险决策表';
CREATE TABLE IF NOT EXISTS login_risk_country_blocks (
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
block_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '拦截 ID',
keyword VARCHAR(128) NOT NULL COMMENT '关键词',
country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT '国家或地区编码',
enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (block_id),
UNIQUE KEY uk_login_risk_country_blocks_keyword (app_code, keyword),
KEY idx_login_risk_country_blocks_enabled (app_code, enabled, country_code),
KEY idx_login_risk_country_blocks_updated (app_code, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录风险国家拦截表';
-- 本地联调测试账号。
-- 密码登录仍以 users.current_display_user_id 为账号password_accounts 只保存 user_id 维度密码身份。
INSERT INTO users (
app_code,
user_id,
default_display_user_id,
current_display_user_id,
current_display_user_id_kind,
current_display_user_id_expires_at_ms,
username,
profile_completed,
profile_completed_at_ms,
onboarding_status,
status,
created_at_ms,
updated_at_ms
)
VALUES (
'lalu',
123456,
'123456',
'123456',
'default',
NULL,
'test_123456',
1,
0,
'completed',
'active',
0,
0
)
ON DUPLICATE KEY UPDATE
current_display_user_id = VALUES(current_display_user_id),
current_display_user_id_kind = VALUES(current_display_user_id_kind),
current_display_user_id_expires_at_ms = VALUES(current_display_user_id_expires_at_ms),
username = VALUES(username),
profile_completed = VALUES(profile_completed),
onboarding_status = VALUES(onboarding_status),
status = VALUES(status),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO user_display_user_ids (
app_code,
display_user_id,
user_id,
display_user_id_kind,
status,
assigned_at_ms,
activated_at_ms,
created_at_ms,
updated_at_ms
)
VALUES ('lalu', '123456', 123456, 'default', 'active', 0, 0, 0, 0)
ON DUPLICATE KEY UPDATE
display_user_id = VALUES(display_user_id),
display_user_id_kind = VALUES(display_user_id_kind),
status = VALUES(status),
activated_at_ms = VALUES(activated_at_ms),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO password_accounts (
app_code,
user_id,
password_hash,
hash_alg,
created_at_ms,
updated_at_ms
)
VALUES (
'lalu',
123456,
'$2a$10$9eyyJvfGdkb3oU8EAPUHiuLz1C/AmhGTU1nq8AeOIMNFwznk7B69G',
'bcrypt',
0,
0
)
ON DUPLICATE KEY UPDATE
password_hash = VALUES(password_hash),
hash_alg = VALUES(hash_alg),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO users (
app_code,
user_id,
default_display_user_id,
current_display_user_id,
current_display_user_id_kind,
current_display_user_id_expires_at_ms,
username,
profile_completed,
profile_completed_at_ms,
onboarding_status,
status,
created_at_ms,
updated_at_ms
)
VALUES (
'lalu',
12345678,
'12345678',
'12345678',
'default',
NULL,
'test_12345678',
1,
0,
'completed',
'active',
0,
0
)
ON DUPLICATE KEY UPDATE
current_display_user_id = VALUES(current_display_user_id),
current_display_user_id_kind = VALUES(current_display_user_id_kind),
current_display_user_id_expires_at_ms = VALUES(current_display_user_id_expires_at_ms),
username = VALUES(username),
profile_completed = VALUES(profile_completed),
onboarding_status = VALUES(onboarding_status),
status = VALUES(status),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO user_display_user_ids (
app_code,
display_user_id,
user_id,
display_user_id_kind,
status,
assigned_at_ms,
activated_at_ms,
created_at_ms,
updated_at_ms
)
VALUES ('lalu', '12345678', 12345678, 'default', 'active', 0, 0, 0, 0)
ON DUPLICATE KEY UPDATE
display_user_id = VALUES(display_user_id),
display_user_id_kind = VALUES(display_user_id_kind),
status = VALUES(status),
activated_at_ms = VALUES(activated_at_ms),
updated_at_ms = VALUES(updated_at_ms);
INSERT INTO password_accounts (
app_code,
user_id,
password_hash,
hash_alg,
created_at_ms,
updated_at_ms
)
VALUES (
'lalu',
12345678,
'$2a$10$2sdtdAzFlPu23vC0vMQT6OIIm5.KCzATuwvn8i09/SKHz.hmkzJce',
'bcrypt',
0,
0
)
ON DUPLICATE KEY UPDATE
password_hash = VALUES(password_hash),
hash_alg = VALUES(hash_alg),
updated_at_ms = VALUES(updated_at_ms);