fix(mining-admin): use Prisma relationMode=prisma for CDC sync tables
Switch to Prisma's "prisma" relation mode to handle CDC event ordering issues. This mode emulates foreign key relations at the Prisma Client layer instead of creating database-level FK constraints, which is the recommended approach for CDC scenarios where event arrival order cannot be guaranteed. Reference: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/relation-mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ea789f7fec
commit
01ff873264
|
|
@ -1,7 +1,9 @@
|
||||||
-- =============================================================================
|
-- =============================================================================
|
||||||
-- 移除 CDC 同步表的外键约束
|
-- 切换到 Prisma relationMode = "prisma"
|
||||||
|
-- 移除数据库层的外键约束,改由 Prisma Client 在应用层模拟外键关系
|
||||||
|
--
|
||||||
-- 原因:CDC 事件异步到达,顺序不可控,子表记录可能在父表记录之前到达
|
-- 原因:CDC 事件异步到达,顺序不可控,子表记录可能在父表记录之前到达
|
||||||
-- 参考:https://estuary.dev/blog/cdc-done-correctly/
|
-- 参考:https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/relation-mode
|
||||||
-- =============================================================================
|
-- =============================================================================
|
||||||
|
|
||||||
-- 移除 synced_contribution_accounts 表的外键约束
|
-- 移除 synced_contribution_accounts 表的外键约束
|
||||||
|
|
@ -19,3 +21,16 @@ DROP CONSTRAINT IF EXISTS "synced_mining_accounts_accountSequence_fkey";
|
||||||
-- 移除 synced_trading_accounts 表的外键约束
|
-- 移除 synced_trading_accounts 表的外键约束
|
||||||
ALTER TABLE "synced_trading_accounts"
|
ALTER TABLE "synced_trading_accounts"
|
||||||
DROP CONSTRAINT IF EXISTS "synced_trading_accounts_accountSequence_fkey";
|
DROP CONSTRAINT IF EXISTS "synced_trading_accounts_accountSequence_fkey";
|
||||||
|
|
||||||
|
-- 为 accountSequence 字段添加索引以优化 JOIN 性能(如果不存在)
|
||||||
|
CREATE INDEX IF NOT EXISTS "synced_contribution_accounts_accountSequence_idx"
|
||||||
|
ON "synced_contribution_accounts"("accountSequence");
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "synced_referrals_accountSequence_idx"
|
||||||
|
ON "synced_referrals"("accountSequence");
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "synced_mining_accounts_accountSequence_idx"
|
||||||
|
ON "synced_mining_accounts"("accountSequence");
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "synced_trading_accounts_accountSequence_idx"
|
||||||
|
ON "synced_trading_accounts"("accountSequence");
|
||||||
|
|
@ -3,8 +3,9 @@ generator client {
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
url = env("DATABASE_URL")
|
url = env("DATABASE_URL")
|
||||||
|
relationMode = "prisma" // CDC场景:Prisma层模拟外键关系,数据库不创建FK约束
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -163,8 +164,11 @@ model SyncedUser {
|
||||||
syncedAt DateTime @default(now())
|
syncedAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
// CDC 同步表不设置外键约束,因为事件到达顺序不可控
|
// 关联同步表
|
||||||
// 使用 accountSequence 作为逻辑关联键,查询时用 LEFT JOIN
|
contributionAccount SyncedContributionAccount?
|
||||||
|
miningAccount SyncedMiningAccount?
|
||||||
|
tradingAccount SyncedTradingAccount?
|
||||||
|
referral SyncedReferral?
|
||||||
|
|
||||||
@@index([phone])
|
@@index([phone])
|
||||||
@@index([status])
|
@@index([status])
|
||||||
|
|
@ -179,7 +183,7 @@ model SyncedUser {
|
||||||
|
|
||||||
model SyncedContributionAccount {
|
model SyncedContributionAccount {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
accountSequence String @unique // 逻辑关联 SyncedUser.accountSequence,无外键约束
|
accountSequence String @unique
|
||||||
personalContribution Decimal @db.Decimal(30, 8) @default(0)
|
personalContribution Decimal @db.Decimal(30, 8) @default(0)
|
||||||
teamLevelContribution Decimal @db.Decimal(30, 8) @default(0)
|
teamLevelContribution Decimal @db.Decimal(30, 8) @default(0)
|
||||||
teamBonusContribution Decimal @db.Decimal(30, 8) @default(0)
|
teamBonusContribution Decimal @db.Decimal(30, 8) @default(0)
|
||||||
|
|
@ -192,6 +196,8 @@ model SyncedContributionAccount {
|
||||||
syncedAt DateTime @default(now())
|
syncedAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
user SyncedUser @relation(fields: [accountSequence], references: [accountSequence])
|
||||||
|
|
||||||
@@map("synced_contribution_accounts")
|
@@map("synced_contribution_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,7 +207,7 @@ model SyncedContributionAccount {
|
||||||
|
|
||||||
model SyncedReferral {
|
model SyncedReferral {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
accountSequence String @unique // 逻辑关联 SyncedUser.accountSequence,无外键约束
|
accountSequence String @unique
|
||||||
referrerAccountSequence String? // 推荐人账户序列号
|
referrerAccountSequence String? // 推荐人账户序列号
|
||||||
referrerUserId BigInt? // 1.0 的 referrer_id
|
referrerUserId BigInt? // 1.0 的 referrer_id
|
||||||
originalUserId BigInt? // 1.0 的 user_id
|
originalUserId BigInt? // 1.0 的 user_id
|
||||||
|
|
@ -210,6 +216,8 @@ model SyncedReferral {
|
||||||
syncedAt DateTime @default(now())
|
syncedAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
user SyncedUser @relation(fields: [accountSequence], references: [accountSequence])
|
||||||
|
|
||||||
@@index([referrerAccountSequence])
|
@@index([referrerAccountSequence])
|
||||||
@@index([depth])
|
@@index([depth])
|
||||||
@@map("synced_referrals")
|
@@map("synced_referrals")
|
||||||
|
|
@ -301,7 +309,7 @@ model SyncedNetworkProgress {
|
||||||
|
|
||||||
model SyncedMiningAccount {
|
model SyncedMiningAccount {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
accountSequence String @unique // 逻辑关联 SyncedUser.accountSequence,无外键约束
|
accountSequence String @unique
|
||||||
totalMined Decimal @db.Decimal(30, 8) @default(0)
|
totalMined Decimal @db.Decimal(30, 8) @default(0)
|
||||||
availableBalance Decimal @db.Decimal(30, 8) @default(0)
|
availableBalance Decimal @db.Decimal(30, 8) @default(0)
|
||||||
frozenBalance Decimal @db.Decimal(30, 8) @default(0)
|
frozenBalance Decimal @db.Decimal(30, 8) @default(0)
|
||||||
|
|
@ -309,6 +317,8 @@ model SyncedMiningAccount {
|
||||||
syncedAt DateTime @default(now())
|
syncedAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
user SyncedUser @relation(fields: [accountSequence], references: [accountSequence])
|
||||||
|
|
||||||
@@map("synced_mining_accounts")
|
@@map("synced_mining_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,7 +328,7 @@ model SyncedMiningAccount {
|
||||||
|
|
||||||
model SyncedTradingAccount {
|
model SyncedTradingAccount {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
accountSequence String @unique // 逻辑关联 SyncedUser.accountSequence,无外键约束
|
accountSequence String @unique
|
||||||
shareBalance Decimal @db.Decimal(30, 8) @default(0)
|
shareBalance Decimal @db.Decimal(30, 8) @default(0)
|
||||||
cashBalance Decimal @db.Decimal(30, 8) @default(0)
|
cashBalance Decimal @db.Decimal(30, 8) @default(0)
|
||||||
frozenShares Decimal @db.Decimal(30, 8) @default(0)
|
frozenShares Decimal @db.Decimal(30, 8) @default(0)
|
||||||
|
|
@ -328,6 +338,8 @@ model SyncedTradingAccount {
|
||||||
syncedAt DateTime @default(now())
|
syncedAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
user SyncedUser @relation(fields: [accountSequence], references: [accountSequence])
|
||||||
|
|
||||||
@@map("synced_trading_accounts")
|
@@map("synced_trading_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue