zoukankan      html  css  js  c++  java
  • 在线修改MySQL大表的表结构

    由于某个临时需求,需要给在线MySQL的某个超过千万的表增加一个字段。此表在设计之时完全按照需求实现,并没有多余的保留字段。

    我们知道在MySQL中如果要执行ALTER TABLE操作,MySQL会通过制作原来表的一个临时副本来工作。对于表结构的修改在副本上施行,然后将新表替换原始表,此时会产生锁表,用户可以从原始表读取数据,而用户的更新和写入操作都会被lock,待新表准备好后写入新表。
    这对于在线的数据量较大的表来说是绝对无法容忍的,并且由于这种在线操作时间会很长,此时如果show processlist,会发现有若干的MySQL进程处于lock状态,当这种进程太多超过单台服务器允许的MySQL进程数,其它进程可能会被拒绝连接。

    有哪些方案可以处理这个问题呢?

    方案1、直接ALTER TABLE
    这个方案只能说这仅仅是一种方案,在某些非实时在线或数据量较小时有较好的表现。

    方案2、模拟数据库修改表结构的操作,在非数据库层实现整个过程。

    1. 实现业务中对于数据的读写分离
    2. 创建一个已经按需求修改好结构的新表
    3. 修改业务逻辑,将读操作指向旧表,将写操作指向新表。如果读旧表没有,再读新表,并将旧的数据写入到新表,当然这一步写入操作我们可以不用,我们可以在后台做一个定时任务将旧数据同步到新表。

    这种方案有一个较大的缺点,需要业务逻辑层配合实现数据的迁移,对于业务逻辑有修改,并且如果有多台机器的话,需要一台一台的修改,较费时间,但是对于MySQL的两种主要存储引擎都适用。


    方案3、facebook online schema change
    facebook的OSC在整体流程上与方案2没有较大的区别,只是它在这里引入了触发器,从而不需要修改业务逻辑,在数据库层就实现了新数据的两个表的同步问题。其大概步骤如下:

    1. 按需求创建新表
    2. 针对原始表创建触发器
    3. 对于原始表的更新操作都会被触发器更新到新表中
    4. 把原始表中的数据复制到新表中
    5. 将新表替换旧表

    fb的osc方案从数据库层解决了方案2的问题,但是它仅支持InnoDB存储引擎。


    方案4、换一个思路,保留字段。
    假设一切可以从头再来,我们也许可以加多一些冗余字段,各个类型都加一些,备用。只是,回不去了!

    方案5、再换一个思路,增加扩展表。
    我们不在原有的表的基础上修改了,以增加扩展表的方式,将新字段的数据写入到扩展表中,修改业务逻辑,这些字段从新表中读取。
    志强同学说这是典型的维表结构设计。
    暂时解决了问题,如果这些字段后续使用频率高的话,可能会有对后期维护或业务有一定的影响。

    后记
    基于现有的需求,只是需要记录新的字段,所以采用了扩展表的方案。

     

    转载【http://www.phppan.com/2012/05/online-schema-change/】

    问题描述

    由于某个临时需求,需要给在线MySQL的某个超过千万的表增加一个字段。此表在设计之时完全按照需求实现,并没有多余的保留字段。

    我们知道在MySQL中如果要执行ALTER TABLE操作,MySQL会通过制作原来表的一个临时副本来工作。对于表结构的修改在副本上施行,然后将新表替换原始表,此时会产生锁表,用户可以从原始表读取数据,而用户的更新和写入操作都会被lock,待新表准备好后写入新表。
    这对于在线的数据量较大的表来说是绝对无法容忍的,并且由于这种在线操作时间会很长,此时如果show processlist,会发现有若干的MySQL进程处于lock状态,当这种进程太多超过单台服务器允许的MySQL进程数,其它进程可能会被拒绝连接。

    有哪些方案可以处理这个问题呢?

    方案1、直接ALTER TABLE
    这个方案只能说这仅仅是一种方案,在某些非实时在线或数据量较小时有较好的表现。

    方案2、模拟数据库修改表结构的操作,在非数据库层实现整个过程。

    1. 实现业务中对于数据的读写分离
    2. 创建一个已经按需求修改好结构的新表
    3. 修改业务逻辑,将读操作指向旧表,将写操作指向新表。如果读旧表没有,再读新表,并将旧的数据写入到新表,当然这一步写入操作我们可以不用,我们可以在后台做一个定时任务将旧数据同步到新表。

    这种方案有一个较大的缺点,需要业务逻辑层配合实现数据的迁移,对于业务逻辑有修改,并且如果有多台机器的话,需要一台一台的修改,较费时间,但是对于MySQL的两种主要存储引擎都适用。


    方案3、facebook online schema change
    facebook的OSC在整体流程上与方案2没有较大的区别,只是它在这里引入了触发器,从而不需要修改业务逻辑,在数据库层就实现了新数据的两个表的同步问题。其大概步骤如下:

    1. 按需求创建新表
    2. 针对原始表创建触发器
    3. 对于原始表的更新操作都会被触发器更新到新表中
    4. 把原始表中的数据复制到新表中
    5. 将新表替换旧表

    fb的osc方案从数据库层解决了方案2的问题,但是它仅支持InnoDB存储引擎。


    方案4、换一个思路,保留字段。
    假设一切可以从头再来,我们也许可以加多一些冗余字段,各个类型都加一些,备用。只是,回不去了!

    方案5、再换一个思路,增加扩展表。
    我们不在原有的表的基础上修改了,以增加扩展表的方式,将新字段的数据写入到扩展表中,修改业务逻辑,这些字段从新表中读取。
    志强同学说这是典型的维表结构设计。
    暂时解决了问题,如果这些字段后续使用频率高的话,可能会有对后期维护或业务有一定的影响。

    后记
    基于现有的需求,只是需要记录新的字段,所以采用了扩展表的方案。

  • 相关阅读:
    那些ubuntu创建用户踩过的坑
    Build tools
    version control(以git为例)讲解
    URI和URL的区别
    HTTP解析过程心得
    函数式编程(functional programming)
    cb45a_c++_STL_算法_删除_(3)_unique(唯一的意思)删除连续性的重复的数据
    cb44a_c++_STL_算法_删除_(2)remove_copy_remove_copy_if
    cb43a_c++_STL_算法_删除_(1)remove_remove_if
    cb42a_c++_STL_算法_替换_replace
  • 原文地址:https://www.cnblogs.com/jamesbd/p/3581957.html
Copyright © 2011-2022 走看看