在线上一个表上执行了alter 增加字段操作,报异常:ERROR 1878 (HY000): Temporary file write failure. 初步怀疑表太大,临时空间不够。
1.查了下表的大小将近28G,索引18G,mysql配置的tmp缓存目录只有2G
select data_length,index_length from tables where table_schema='dbName' and table_name = 'tableName';
select concat(round(sum(data_length/1024/1024),2),'MB') as data_length_MB, concat(round(sum(index_length/1024/1024),2),'MB') as index_length_MB
from tables where table_schema='dbName' and table_name = 'tableName';
解决方法:
一、更改mysql 的tmp目录,让tmp目录空间更大,然后重新执行 变更sql语句。
mkdir -p /data/tmp
chown -R mysql:mysql /data/tmp
chmod a+w /data/tmp
vim /etc/my.cnf #把tmpdir设置到 /data/tmp
tmpdir=/data/tmp
service mysqld restart 需要重启mysql服,对线上业务影响较大。
innodb 在 ddl 的时候所执行的操作:
1. 按照原始表 (original_table) 的表结构和 ddl 语句,新建一个不可见的临时表 (temporary_table)
2. 在原表上面加上 WRITE LOCK 阻塞所有的更新操作 (insert、delete、update等操作)
3. 执行 insert into tmp_table select * from original_table
4. rename original_table 和 tmp_table 最后 drop original_table
5. 最后释放掉 write lock
二、采用pt-online-schema-change方式进行修改。
「来自 2018 年的补充:目前 MySQL 自己也提供了 onlineddl 的工具,在数据量不大的时候还是非常好用的,直接指定 inplace 也可以轻松达到不锁表加字段的效果」。
通过以上的步骤我们可以很容易的发现,这样操作在表锁定的情况是只能查询,不能写入。为了解决这个问题所以 percona 公司推出了一个不会阻塞的工具 pt-online-schema-change。
这里不得不再次介绍一下 pt-online-schema-change 是怎么做到在不阻塞写入的情况下改动数据库的:
1. 首先创建一个和你要执行的 alter 操作的表一样的空的表结构。
2. 执行我们赋予的表结构的修改,然后 copy 原表中的数据到新表里面。
3. 在原表上创建一个触发器在数据 copy 的过程中,将原表的更新数据的操作全部更新到新的表中来。 这里特别注意一下,如果原表中已经定义了触发器那么工具就不能工作了,因为 pt 使用到了数据库的触发器。
4. copy 完成之后,用 rename table 新表代替原表,默认删除原表。
转自:https://blog.csdn.net/educast/article/details/89520434
原理 pt-online-schema-change 使用解析:https://blog.csdn.net/isoleo/article/details/103818332