在線上一個表上執行了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