yanderong
2 天以前 686790777f722b0621bcc20e550d15965cda7b67
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
-- 充电订单改造(order库):三张订单表新增「释放幂等标记 / 结算完成标记」列
-- 目的:
--   1) lock_released(锁定额度是否已释放):企业账户/白名单锁定额的释放路径(建单回滚、启动失败关单、
--      无实时数据关单等)先用条件更新抢占该标记,保证同一订单的锁定额在多路径并发或重复补偿下只释放一次;
--      释放失败时把标记回滚为 0,留待后续补偿或人工重试;
--      t_card_charging_order 已随刷卡改造建列(20260930_card_order_lock_released.sql),本脚本补齐
--      t_charging_order(充电桩订单)与 t_vin_charging_order(VIN 订单,订单实体父类字段会参与 SELECT,必须建列);
--   2) settle_status(结算完成标记):企业账户订单结算成功后置 1,兜底扫描(findEndChargingOrder 等)
--      不再把已结算/已终结的订单回退重跑,避免重复结算与重复扣款。
-- 创建日期: 2026-09-30
-- 目标库:charging_pile_order
--   分片表:t_charging_order、t_vin_charging_order、t_card_charging_order(Mycat 逻辑表,物理分表逐片执行)
-- 执行方式:
--   1) 首选「小节 A」经数据库代理(MyCat 8066)执行,代理会把 DDL 广播到全部物理分表;
--   2) 代理不支持分片表 DDL 时,改用「小节 B」直连后端 MySQL 实例执行(存储过程,逐物理分表,幂等);
--   3) 最后执行「小节 C」回查校验。
-- 幂等说明:小节 A 为裸 ALTER,重复执行会报 Duplicate column,忽略即可(以小节 C 回查为准);
--           小节 B 先查 information_schema 再变更,可重复执行。
 
-- ============ 小节 A:经代理执行(推荐) ============
USE `charging_pile_order`;
 
ALTER TABLE `t_charging_order`
  ADD COLUMN `lock_released` tinyint(1) NOT NULL DEFAULT 0 COMMENT '锁定额度是否已释放(0=未释放,1=已释放;防重复释放幂等标记)';
 
ALTER TABLE `t_charging_order`
  ADD COLUMN `settle_status` tinyint(1) DEFAULT NULL COMMENT '结算完成标记(NULL/0=未结算,1=已结算;兜底扫描不回退已结算订单)';
 
ALTER TABLE `t_vin_charging_order`
  ADD COLUMN `lock_released` tinyint(1) NOT NULL DEFAULT 0 COMMENT '锁定额度是否已释放(0=未释放,1=已释放;防重复释放幂等标记)';
 
ALTER TABLE `t_vin_charging_order`
  ADD COLUMN `settle_status` tinyint(1) DEFAULT NULL COMMENT '结算完成标记(NULL/0=未结算,1=已结算;兜底扫描不回退已结算订单)';
 
ALTER TABLE `t_card_charging_order`
  ADD COLUMN `settle_status` tinyint(1) DEFAULT NULL COMMENT '结算完成标记(NULL/0=未结算,1=已结算;兜底扫描不回退已结算订单)';
 
-- ============ 小节 B:直连后端 MySQL 实例执行(代理不可用时分表执行,幂等) ============
USE `charging_pile_order`;
 
DROP PROCEDURE IF EXISTS `add_charging_order_lock_released`;
DELIMITER $$
CREATE PROCEDURE `add_charging_order_lock_released`()
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE target_table VARCHAR(64);
    DECLARE column_exists INT DEFAULT 0;
 
    -- 覆盖逻辑表(若物理存在)与 TBPARTITION 物理分表
    DECLARE table_cursor CURSOR FOR
        SELECT t.table_name
        FROM information_schema.tables t
        WHERE t.table_schema = DATABASE()
          AND t.table_name REGEXP '^t_charging_order(_[0-9]+)?$|^t_vin_charging_order(_[0-9]+)?$|^t_card_charging_order(_[0-9]+)?$';
 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
 
    OPEN table_cursor;
    table_loop: LOOP
        FETCH table_cursor INTO target_table;
        IF done = 1 THEN
            LEAVE table_loop;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'lock_released';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `lock_released` tinyint(1) NOT NULL DEFAULT 0 COMMENT ''锁定额度是否已释放(0=未释放,1=已释放;防重复释放幂等标记)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'settle_status';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `settle_status` tinyint(1) DEFAULT NULL COMMENT ''结算完成标记(NULL/0=未结算,1=已结算;兜底扫描不回退已结算订单)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
    END LOOP;
    CLOSE table_cursor;
END$$
DELIMITER ;
 
CALL `add_charging_order_lock_released`();
DROP PROCEDURE IF EXISTS `add_charging_order_lock_released`;
 
-- ============ 小节 C:回查校验 ============
-- 1) 列存在性与注释(三张订单表均应覆盖逻辑表与全部物理分表):
--    SELECT table_name, column_name, column_type, column_default, column_comment
--    FROM information_schema.columns
--    WHERE table_schema = 'charging_pile_order'
--      AND column_name IN ('lock_released', 'settle_status')
--    ORDER BY table_name, column_name;
--    预期:t_charging_order / t_vin_charging_order / t_card_charging_order 及各自物理分表均存在两列,
--          lock_released column_default=0、column_comment 中文无乱码
-- 2) 历史订单默认未释放、未结算标记为空:
--    SELECT COUNT(*) FROM t_charging_order WHERE lock_released = 0 AND settle_status IS NULL;
--    预期:等于存量订单数(存量订单按「实时查询 + 回填」兼容路径处理)