docs(review): add remediation plans and readiness artifacts
Add design, review, and production-readiness documents for the April remediation cycle.\nInclude supporting SQL and supply-api operational design notes so review conclusions and implementation guidance stay versioned together.
This commit is contained in:
102
supply-api/sql/postgresql/audit_events_migration_v1_to_v2.sql
Normal file
102
supply-api/sql/postgresql/audit_events_migration_v1_to_v2.sql
Normal file
@@ -0,0 +1,102 @@
|
||||
-- ============================================================================
|
||||
-- 审计事件表 Schema 迁移 v1 -> v2
|
||||
-- 问题: 数据库中的 audit_events 表是旧版 schema,与代码中的 model 不匹配
|
||||
--
|
||||
-- 旧版 schema (当前生产表):
|
||||
-- domain_code, action_code, severity, client_ip, before_data, after_data
|
||||
--
|
||||
-- 新版 schema (代码期望):
|
||||
-- event_id, event_name, event_category, timestamp, timestamp_ms,
|
||||
-- action, source_ip, operator_id, operator_type 等
|
||||
-- ============================================================================
|
||||
|
||||
-- 1. 备份现有数据(如果表中有数据)
|
||||
CREATE TABLE IF NOT EXISTS audit_events_backup AS
|
||||
SELECT * FROM audit_events WHERE 1=0;
|
||||
|
||||
-- 如果有数据则备份
|
||||
INSERT INTO audit_events_backup SELECT * FROM audit_events;
|
||||
|
||||
-- 2. 删除旧表和约束
|
||||
DROP TABLE IF EXISTS audit_events CASCADE;
|
||||
|
||||
-- 3. 创建新表(使用 partition_strategy_v1.sql 中的定义)
|
||||
CREATE TABLE IF NOT EXISTS audit_events (
|
||||
id BIGSERIAL,
|
||||
event_id VARCHAR(100) NOT NULL,
|
||||
event_name VARCHAR(100) NOT NULL,
|
||||
event_category VARCHAR(50),
|
||||
event_sub_category VARCHAR(50),
|
||||
timestamp TIMESTAMPTZ NOT NULL,
|
||||
timestamp_ms BIGINT NOT NULL,
|
||||
request_id VARCHAR(100),
|
||||
idempotency_key VARCHAR(128),
|
||||
tenant_id BIGINT,
|
||||
object_type VARCHAR(100),
|
||||
object_id VARCHAR(100),
|
||||
action VARCHAR(100) NOT NULL,
|
||||
result_code VARCHAR(50),
|
||||
source_ip VARCHAR(50),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id, timestamp)
|
||||
) PARTITION BY RANGE (timestamp);
|
||||
|
||||
-- 4. 创建索引
|
||||
CREATE INDEX idx_audit_events_tenant_id ON audit_events(tenant_id);
|
||||
CREATE INDEX idx_audit_events_request_id ON audit_events(request_id);
|
||||
CREATE INDEX idx_audit_events_created_at ON audit_events(created_at);
|
||||
CREATE INDEX idx_audit_events_object ON audit_events(object_type, object_id);
|
||||
|
||||
-- 5. 创建初始分区(过去12个月 + 未来3个月)
|
||||
DO $$
|
||||
DECLARE
|
||||
i INT;
|
||||
target_date DATE;
|
||||
partition_name TEXT;
|
||||
start_date DATE;
|
||||
end_date DATE;
|
||||
BEGIN
|
||||
-- 过去12个月
|
||||
FOR i IN -12..0 LOOP
|
||||
target_date := (CURRENT_DATE + (i || ' months')::INTERVAL)::DATE;
|
||||
start_date := date_trunc('month', target_date)::DATE;
|
||||
end_date := (start_date + INTERVAL '1 month')::DATE;
|
||||
partition_name := 'audit_events_' || to_char(start_date, 'YYYY_MM');
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_class WHERE relname = partition_name
|
||||
) THEN
|
||||
EXECUTE format(
|
||||
'CREATE TABLE %I PARTITION OF audit_events FOR VALUES FROM (%L) TO (%L)',
|
||||
partition_name, start_date, end_date
|
||||
);
|
||||
RAISE NOTICE 'Created partition: %', partition_name;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- 未来3个月
|
||||
FOR i IN 1..3 LOOP
|
||||
target_date := (CURRENT_DATE + (i || ' months')::INTERVAL)::DATE;
|
||||
start_date := date_trunc('month', target_date)::DATE;
|
||||
end_date := (start_date + INTERVAL '1 month')::DATE;
|
||||
partition_name := 'audit_events_' || to_char(start_date, 'YYYY_MM');
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_class WHERE relname = partition_name
|
||||
) THEN
|
||||
EXECUTE format(
|
||||
'CREATE TABLE %I PARTITION OF audit_events FOR VALUES FROM (%L) TO (%L)',
|
||||
partition_name, start_date, end_date
|
||||
);
|
||||
RAISE NOTICE 'Created partition: %', partition_name;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
-- 6. 验证
|
||||
SELECT table_name, count(*) as partition_count
|
||||
FROM pg_tables
|
||||
WHERE table_name LIKE 'audit_events%' AND table_name != 'audit_events' AND table_name != 'audit_events_backup'
|
||||
GROUP BY table_name;
|
||||
|
||||
COMMENT ON TABLE audit_events IS '审计事件表 - 按月分区,保留12个月';
|
||||
Reference in New Issue
Block a user