a
This commit is contained in:
parent
b2411fe745
commit
be44cd02a7
50
backend/database/fix_exit_order_id_unique.sql
Normal file
50
backend/database/fix_exit_order_id_unique.sql
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
-- 修复 exit_order_id 唯一约束问题
|
||||
-- 问题:exit_order_id 有 UNIQUE 约束,但在状态同步时,同一个订单可能被多次更新,导致重复键错误
|
||||
-- 解决方案:移除 UNIQUE 约束,保留索引以便快速查询
|
||||
|
||||
USE `auto_trade_sys`;
|
||||
|
||||
-- 1. 删除唯一约束(如果存在)
|
||||
-- 注意:MySQL 中,如果字段有 UNIQUE 约束,删除索引会同时删除唯一约束
|
||||
-- 先检查是否存在唯一索引
|
||||
SET @index_exists = (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = 'auto_trade_sys'
|
||||
AND table_name = 'trades'
|
||||
AND index_name = 'exit_order_id'
|
||||
AND non_unique = 0
|
||||
);
|
||||
|
||||
-- 如果存在唯一索引,删除它
|
||||
SET @sql = IF(@index_exists > 0,
|
||||
'ALTER TABLE `trades` DROP INDEX `exit_order_id`',
|
||||
'SELECT "exit_order_id 唯一索引不存在,跳过删除" as message'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 2. 重新添加普通索引(非唯一)
|
||||
-- 先检查是否已存在普通索引
|
||||
SET @normal_index_exists = (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = 'auto_trade_sys'
|
||||
AND table_name = 'trades'
|
||||
AND index_name = 'idx_exit_order_id'
|
||||
);
|
||||
|
||||
-- 如果不存在普通索引,添加它
|
||||
SET @sql2 = IF(@normal_index_exists = 0,
|
||||
'ALTER TABLE `trades` ADD INDEX `idx_exit_order_id` (`exit_order_id`)',
|
||||
'SELECT "idx_exit_order_id 索引已存在,跳过添加" as message'
|
||||
);
|
||||
PREPARE stmt2 FROM @sql2;
|
||||
EXECUTE stmt2;
|
||||
DEALLOCATE PREPARE stmt2;
|
||||
|
||||
-- 验证:检查表结构
|
||||
-- SHOW CREATE TABLE `trades`;
|
||||
-- 或者
|
||||
-- SHOW INDEX FROM `trades` WHERE Column_name = 'exit_order_id';
|
||||
|
|
@ -120,16 +120,63 @@ class Trade:
|
|||
pnl: 盈亏
|
||||
pnl_percent: 盈亏百分比
|
||||
exit_order_id: 币安平仓订单号(可选,用于对账)
|
||||
|
||||
注意:如果 exit_order_id 已存在且属于其他交易记录,会跳过更新 exit_order_id 以避免唯一约束冲突
|
||||
"""
|
||||
exit_time = get_beijing_time()
|
||||
db.execute_update(
|
||||
"""UPDATE trades
|
||||
SET exit_price = %s, exit_time = %s,
|
||||
exit_reason = %s, pnl = %s, pnl_percent = %s, status = 'closed',
|
||||
exit_order_id = %s
|
||||
WHERE id = %s""",
|
||||
(exit_price, exit_time, exit_reason, pnl, pnl_percent, exit_order_id, trade_id)
|
||||
)
|
||||
|
||||
# 如果提供了 exit_order_id,先检查是否已被其他交易记录使用
|
||||
if exit_order_id is not None:
|
||||
try:
|
||||
existing_trade = Trade.get_by_exit_order_id(exit_order_id)
|
||||
if existing_trade and existing_trade['id'] != trade_id:
|
||||
# 如果 exit_order_id 已被其他交易记录使用,记录警告但不更新 exit_order_id
|
||||
logger.warning(
|
||||
f"交易记录 {trade_id} 的 exit_order_id {exit_order_id} 已被交易记录 {existing_trade['id']} 使用,"
|
||||
f"跳过更新 exit_order_id,只更新其他字段"
|
||||
)
|
||||
# 只更新其他字段,不更新 exit_order_id
|
||||
db.execute_update(
|
||||
"""UPDATE trades
|
||||
SET exit_price = %s, exit_time = %s,
|
||||
exit_reason = %s, pnl = %s, pnl_percent = %s, status = 'closed'
|
||||
WHERE id = %s""",
|
||||
(exit_price, exit_time, exit_reason, pnl, pnl_percent, trade_id)
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
# 如果查询失败,记录警告但继续正常更新
|
||||
logger.warning(f"检查 exit_order_id {exit_order_id} 时出错: {e},继续正常更新")
|
||||
|
||||
# 正常更新(包括 exit_order_id)
|
||||
try:
|
||||
db.execute_update(
|
||||
"""UPDATE trades
|
||||
SET exit_price = %s, exit_time = %s,
|
||||
exit_reason = %s, pnl = %s, pnl_percent = %s, status = 'closed',
|
||||
exit_order_id = %s
|
||||
WHERE id = %s""",
|
||||
(exit_price, exit_time, exit_reason, pnl, pnl_percent, exit_order_id, trade_id)
|
||||
)
|
||||
except Exception as e:
|
||||
# 如果更新失败(可能是唯一约束冲突),尝试不更新 exit_order_id
|
||||
error_str = str(e)
|
||||
if "Duplicate entry" in error_str and "exit_order_id" in error_str:
|
||||
logger.warning(
|
||||
f"更新交易记录 {trade_id} 时 exit_order_id {exit_order_id} 唯一约束冲突,"
|
||||
f"尝试不更新 exit_order_id"
|
||||
)
|
||||
# 只更新其他字段,不更新 exit_order_id
|
||||
db.execute_update(
|
||||
"""UPDATE trades
|
||||
SET exit_price = %s, exit_time = %s,
|
||||
exit_reason = %s, pnl = %s, pnl_percent = %s, status = 'closed'
|
||||
WHERE id = %s""",
|
||||
(exit_price, exit_time, exit_reason, pnl, pnl_percent, trade_id)
|
||||
)
|
||||
else:
|
||||
# 其他错误,重新抛出
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
def get_by_entry_order_id(entry_order_id):
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user