暂无图片
mysql 更新表结构 锁表问题
我来答
分享
www
2024-11-11
mysql 更新表结构 锁表问题

10个以上的mysql 通过工具在线批量更新表结构,加字段或者索引,生产一直在跑业务, 如何防止产生元数据锁,导致业务被阻塞。

我来答
添加附件
收藏
分享
问题补充
2条回答
默认
最新
黄山谷

在MySQL中,进行表结构的批量更新(如添加字段或索引)时,元数据锁(metadata locks, MDL)可能会导致其他正在运行的业务被阻塞,尤其是在高并发生产环境中。这是因为 MySQL 会在更改表结构时锁住相关的元数据,而此时其他事务如果试图访问同一个表,可能会被阻塞直到表结构更新完成。

为了防止元数据锁导致的业务阻塞,可以采取以下几种策略:

  1. 使用pt-online-schema-change工具(Percona Toolkit)
    Percona Toolkit 提供了 pt-online-schema-change 工具,可以在线非阻塞地修改表结构,包括添加字段、索引等操作。这个工具的原理是通过创建一个临时副本表,逐步将数据从原表迁移到副本表中,从而避免直接修改表结构时锁住表的数据。

优点:
完全避免了元数据锁。
可以在表结构更改时,仍然允许正常的读写操作。
支持并发事务,修改操作会在后台进行。
使用方法:
pt-online-schema-change --alter “ADD COLUMN new_column INT” --execute --host= --user= --password= --database= --table=


该工具会在后台完成表结构的修改,不会阻塞业务操作。

  1. 使用 gh-ost 工具(GitHub的在线表结构迁移工具)
    gh-ost 是另一种在线修改表结构的工具,由 GitHub 提供。类似于 pt-online-schema-change,gh-ost 也通过创建一个新的副本表来进行结构变更,并且通过迁移数据来逐步更新表,不会直接锁住表。

优点:
适用于高并发、大数据量环境。
支持在线迁移,避免阻塞。
可以在不锁表的情况下应用更改。
使用方法:
gh-ost --alter=“ADD COLUMN new_column INT” --host= --user= --password= --database= --table=

--approve-renaming
3. 在低峰时段进行表结构修改
如果无法使用 pt-online-schema-change 或 gh-ost,可以考虑在业务的低峰时段进行表结构的修改操作。这通常需要提前规划,确保不会影响到重要业务。

计划业务低峰期,如夜间或系统负载较低的时段,进行修改操作。
在此期间,可以暂停部分不关键的任务或减少并发,降低元数据锁争用的风险。
4. 通过锁粒度控制减少元数据锁的时间
如果在应用字段或索引时无法使用在线工具(如 pt-online-schema-change),可以考虑调整 DDL 操作的锁粒度,特别是在 MySQL 5.6 及以上版本中,MySQL 提供了 LOCK=NONE 的选项,这样可以尽量避免表级锁定。

在 MySQL 5.6 及以上版本中,ALTER TABLE 支持在线添加索引(ONLINE)和无需锁表的操作,尽量选择支持 ONLINE 操作的场景。

示例:添加索引时使用 ONLINE:
ALTER TABLE your_table ADD INDEX idx_column_name (column_name) ALGORITHM=INPLACE, LOCK=NONE;
这种方式可以减少表的锁定时间,尽量避免元数据锁对业务的影响。

  1. 增加事务隔离级别
    在某些情况下,通过增加事务隔离级别(如使用 READ COMMITTED 或 READ UNCOMMITTED)来减少锁定争用和元数据锁的影响。但这种方法需要慎用,可能会导致脏读等问题,建议仅在不影响数据一致性的情况下使用。

  2. 使用分区表
    如果表的大小和数据量非常大,可以考虑将表分区,通过分区表进行数据操作和结构变更。对分区表的操作(尤其是添加字段和索引)通常比操作非分区表更加平滑。

对分区表进行表结构修改时,通常不会对整个表加锁,而只会对特定的分区加锁,减少对业务的影响。
7. 提前进行性能测试和负载测试
在正式生产环境中进行批量更新表结构之前,进行压力测试和负载测试,尤其是在数据库负载较高时,测试表结构更新操作对数据库性能和业务影响的程度。这可以帮助你提前识别潜在的锁竞争和性能瓶颈。

总结:
为了避免 MySQL 中的元数据锁导致生产业务被阻塞,最佳的策略是使用在线迁移工具(如 pt-online-schema-change 或 gh-ost),这些工具可以在不锁表的情况下进行表结构更新,保证业务持续运行。若无法使用这些工具,计划在低峰时段进行修改,并考虑使用更精细的锁策略来减少业务中断时间。

暂无图片 评论
暂无图片 有用 2
打赏 0
暂无图片
test

5.7之后版本支持online ddl,如果相关表上无业务上相关的大事务,理论上元数据锁时间很短,不会导致业务被阻塞。

但需要考虑此时主从切换,以及只读从库延迟的风险。

尽量在业务低峰期做。

暂无图片 评论
暂无图片 有用 2
打赏 0
回答交流
Markdown


请输入正文
提交
相关推荐
ActionDB和OceanBase之间是什么关系?
回答 2
原来ActionDB是基于OceanBase的开源内核开发的,想问一下,ActionDB和OceanBase在日常维护和管理方面有什么区别?比如在备份、恢复、监控等操作上,有没有不同的工具或方法?
show master status;输出了3个gtid,请问是什么原因?
回答 2
如果涉及利用主从切换做迁移的场景时,从库提主之前,没有resetmaster,从库会在涉及变更时,生成一个新的从库的UUID。之前从主从同步,从主库同步过来的GTID也会保留下来,就有了两个GTID。
linux下yum安装mysql,怎么配置大小写
回答 1
已采纳
配置大小写和是不是yum没关系。都是这个参数owercasetablenames
现在MySQL8建议使用 utf8mb4,有些表只存一些基本数据,不涉及表情,能用utf8mb3吗?
回答 4
不涉及到emoj的和特殊字符的就用utf8/utf8mb3, 能节省很多空间的(每行能存储更多的字符), utf8mb4占用的空间会更多.  选择字符集可以根据
mysql 5.7单机最大数据量能支撑到多少?
回答 1
已采纳
从官方资料看,innodb单表最大64T。你所谓的抗不住是指的存储还是性能。存储看硬件。性能看SQL,写的好的千万级别下单表一点问题都没有。过亿的表只要SQL执行计划好,没有问题。
mysql关于多表join关联的执行流程
回答 5
在驱动表上建立条件过滤索引。在被驱动表上建立关联字段索引
请问各位大佬mysql杀会话问题。kill命令是不是只能杀前台会话?
回答 4
已采纳
什么叫前台会话?它kill就是终止一个线程啊,连接也断掉。如果用的是killquery则终止连接当前正在执行的语句,而保留连接不断。
Mysql Timestamp 2038年
回答 1
可以将timestamp改为整数类型,用来保存时间戳,在程序中再进行转换。也可以使用datetime类型来代替timestamp类型,因为datetime类型不会受到这个限制。
innodb_flush_log_at_trx_commit=0 存在的意义是什么?
回答 2
已采纳
总有极端。我也认为哪里那么巧正好断电?我就遇到过一次,不是这个参数,而是syncbinlog。也是012这种。那个值写了16.结果就是binlog不全。奇葩吧。理论如果没有极端问题,都不用写日志。但是
有没有什么操作能够导出 MySQL 中每张表的数据量,日常各表的操作情况、数据库的访问情况?
回答 1
每张表的数据量(参考下面sql,leftjoin两次就能得到每张表数据量了)selecttablerowsas‘表数据总量’frominformationschema.tableswheretable