Description:
We created an index on a disk with a sector size of 4096 bytes but got an error of Temporary file write failure and found that io buffer memory address is not aligned with IO_BLOCK_SIZE(4k), so direct io pwrite and pread operations will fail. The following is the related bug code:
diff --git a/storage/innobase/ddl/ddl0builder.cc b/storage/innobase/ddl/ddl0builder.cc
index af9fd0c32f5..779ece73753 100644
--- a/storage/innobase/ddl/ddl0builder.cc
+++ b/storage/innobase/ddl/ddl0builder.cc
@@ -673,7 +673,7 @@ dberr_t Builder::init(Cursor &cursor, size_t n_threads) noexcept {
thread_ctx->m_aligned_buffer =
ut::make_unique_aligned<byte[]>(ut::make_psi_memory_key(mem_key_ddl),
- UNIV_SECTOR_SIZE, buffer_size.second);
+ IO_BLOCK_SIZE, buffer_size.second);
if (!thread_ctx->m_aligned_buffer) {
return DB_OUT_OF_MEMORY;
diff --git a/storage/innobase/ddl/ddl0file-reader.cc b/storage/innobase/ddl/ddl0file-reader.cc
index 3581b1c8868..c8a94bd66ae 100644
--- a/storage/innobase/ddl/ddl0file-reader.cc
+++ b/storage/innobase/ddl/ddl0file-reader.cc
@@ -47,7 +47,7 @@ dberr_t File_reader::prepare() noexcept {
}
m_aligned_buffer = ut::make_unique_aligned<byte[]>(
- ut::make_psi_memory_key(mem_key_ddl), UNIV_SECTOR_SIZE, m_buffer_size);
+ ut::make_psi_memory_key(mem_key_ddl), IO_BLOCK_SIZE, m_buffer_size);
if (!m_aligned_buffer) {
return DB_OUT_OF_MEMORY;
How to repeat:
1. The tmpdir must be on a disk with a sector size of 4096 bytes.
2. Execute the following SQL:
mysql> create table t1(id int, name varchar(128));
Query OK, 0 rows affected (0.82 sec)
mysql> insert into t1 values(1, repeat('a', 32));
Query OK, 1 row affected (0.00 sec)
mysql> alter table t1 add index name_idx(name);
ERROR 1878 (HY000): Temporary file write failure.
Suggested fix:
When allocating memory, use IO_BLOCK_SIZE as the alignment size. We set the global innodb_disable_sort_file_cache = 0 to avoid direct IO operations, which can also bypass this problem.