🔐🔐🔐 数据库大表,加字段,卡死导致损失惨重!


大表(千万级订单表),在跑,里面关联很多业务,要新增字段,

这时,你去加,所有业务在执行命令的那一秒全部卡死,导致全公司损失惨重,这还不得赔得底裤都不剩...

问题背景

在大数据量表(如万级订单表)上直接执行 ALTER TABLE 新增字段会导致锁表,阻塞读写请求,可能引发超时、连接池耗尽甚至应用崩溃。

🔐锁表

DDL通常会导致锁表。

啥叫锁表

定义:是指数据库在执行某些操作时,限制其他会话的访问,目的是保证数据的一致性完整性,是数据库并发控制基础机制

啥时候会导致锁表

  • 执行DDL操作(如ALTER TABLE添加列)
  • 执行大量数据修改(eg: 大量UPDATE
  • 显式用LOCK TABLE语句
  • 某些特定查询(eg:SELECT FOR UPDATE)

性能影响

  • 导致查询排队等待
  • 可能引发连接池耗尽
  • 极端情况下导致应用超时

eg:

sql 复制代码
-- 会话1执行(会锁表)
ALTER TABLE orders ADD COLUMN discount DECIMAL(10,2);

-- 会话2尝试查询(会被阻塞)
SELECT * FROM orders WHERE user_id=100;

解决方案与操作代码

1. 主从架构处理

  • 适用场景:主库写,从库读的MySQL主从复制环境。

  • 步骤与代码

    sql 复制代码
    -- 1. 停止主从复制
    STOP SLAVE;
    
    -- 2. 在从库执行新增字段(无锁表风险,因从库已停止同步)
    ALTER TABLE orders ADD COLUMN new_field VARCHAR(255);
    
    -- 3. 重启主从复制并检查延迟
    START SLAVE;
    SHOW SLAVE STATUS\G  -- 确认 'Seconds_Behind_Master' 归零
    
    -- 4. 切换主从角色后重复操作主库
  • 风险:需手动切换主从,操作复杂且短暂不可用。

2. 在线DDL工具(pt-online-schema-change)

  • 工具安装

    bash 复制代码
    sudo apt-get install percona-toolkit  # Debian/Ubuntu
  • 执行命令

    bash 复制代码
    pt-online-schema-change \
      --alter="ADD COLUMN new_field VARCHAR(255)" \
      D=database,t=orders \
      --execute
  • 原理 :创建临时表(也叫幽灵👻表)同步数据,原子切换表名。

  • 注意:需监控磁盘空间和数据库负载。

幽灵👻表

主要 DDL 操作包括

  • CREATE - 创建数据库对象(表、视图、索引等)

    sql 复制代码
    CREATE TABLE users (id INT, name VARCHAR(50));
  • ALTER - 修改现有对象结构

    sql 复制代码
    ALTER TABLE users ADD COLUMN email VARCHAR(100);
  • DROP - 删除对象

    sql 复制代码
    DROP TABLE users;
  • TRUNCATE - 清空表数据(保留结构)

    sql 复制代码
    TRUNCATE TABLE logs;
  • RENAME - 重命名对象(部分数据库支持)

    sql 复制代码
    RENAME TABLE old_name TO new_name;

以下三种方法与前两种不同,以此为河界:


3. 扩展新表(低风险推荐)

  • 操作代码

    sql 复制代码
    -- 1. 创建新表存储扩展字段
    CREATE TABLE orders_extension (
      order_id BIGINT PRIMARY KEY,
      new_field VARCHAR(255),
      FOREIGN KEY (order_id) REFERENCES orders(id)
    );
    
    -- 2. 应用层查询时联表(示例:Java MyBatis)
    @Select("SELECT o.*, e.new_field FROM orders o LEFT JOIN orders_extension e ON o.id = e.order_id WHERE o.id = #{id}")
    Order getOrderWithExtension(Long id);
  • 优点:零锁表风险,适合高频变更需求。

4. 预留字段(提前设计)

  • 建表示例

    sql 复制代码
    CREATE TABLE orders (
      id BIGINT PRIMARY KEY,
      reserved_json JSON,  -- 存储未来动态字段
      reserved_field1 VARCHAR(255),
      reserved_field2 INT
    );
  • 使用示例

    sql 复制代码
    UPDATE orders SET reserved_json = JSON_SET(reserved_json, '$.new_property', 'value') WHERE id = 1;

5. 业务优化(非数据库方案)

  • 临时数据存Redis

    java 复制代码
    // Spring Boot示例
    @Cacheable(value = "order:extensions", key = "#orderId")
    public String getOrderExtension(Long orderId) {
      return "临时数据";
    }

总结与选型建议

方案 风险 适用场景 推荐指数
主从架构 已具备主从且允许停机维护 ⭐⭐
在线DDL工具 专业DBA团队 ⭐⭐⭐
扩展新表 高频字段变更 ⭐⭐⭐⭐
预留字段 初期设计阶段 ⭐⭐⭐
业务优化(非DB) 最低 非核心数据或临时需求 ⭐⭐⭐⭐

以上任何操作都需胆大心细,同时需熟练。

相关推荐
北京_宏哥1 分钟前
🔥《刚刚问世》系列初窥篇-Java+Playwright自动化测试-32- 操作日历时间控件-下篇(详细教程)
java·前端·面试
王维志6 分钟前
⏱ TimeSpan:C#时间间隔结构
前端·后端·c#·.net
阿幸软件杂货间14 分钟前
【最新版】Edge浏览器(官方版)安装包_Edge浏览器(官方版)安装教程
前端·edge
RaidenLiu22 分钟前
Flutter 状态管理:Provider 入门与实战
前端·flutter
隔壁老王z27 分钟前
设计实现一个Web 终端:基于 Vue 3 和 Xterm.js 的实践
前端·iterm
中微子28 分钟前
简单介绍跨域资源共享(CORS)
前端
極光未晚31 分钟前
Vue 项目 webpack 打包体积分析:从 “盲猜优化” 到 “精准瘦身”
前端·vue.js·性能优化
刘小筛38 分钟前
Ant Design Vue (2x) 按钮(button)单击后离开,按钮状态无变化
前端
mogullzr41 分钟前
4.1.ByteOJ用户模块——登录注册功能(RSA + TimeStamp加密过)
前端·后端
鹏多多.42 分钟前
flutter-使用AnimatedDefaultTextStyle实现文本动画
android·前端·css·flutter·ios·html5·web