Mysql

當 MySQL/InnoDB 緩衝池大小較小並且執行大型事務導致緩衝池溢出時會發生什麼?

  • October 6, 2019

假設我們有一個執行 50,000 次插入的事務,它弄髒了大約 600 MB 的數據庫。如果緩衝池大小為 128 MB,則在事務執行時緩衝池中將存在臟頁,需要將這些臟頁逐出以騰出空間。我的問題是,MySQL/InnoDB 對這些臟的未送出頁面做了什麼?

5天前我剛遇到一個問題:InnoDB錯誤和MyISAM數據庫崩潰?

在實時聊天會話中對問題進行故障排除時,我發現臨時 InnoDB 表中的髒頁佔用了 InnoDB 緩衝池。文件 ibtmp 為 482MB,其中 75% 的緩衝池是臟的,因為innodb_max_dirty_pages_pct為 75。緩衝池只有 128M。那麼,會發生什麼?

當緩衝池太小時(這是我遇到的一個幾乎空的數據庫)時,緩衝池必須非常頻繁地刷新。

如果你執行SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool%';,你會看到類似這樣的東西:

mysql> SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool%';
+---------------------------------------+--------------------------------------------------+
| Variable_name                         | Value                                            |
+---------------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_dump_status        | Dumping of buffer pool not started               |
| Innodb_buffer_pool_load_status        | Buffer pool(s) load completed at 190925  9:50:58 |
| Innodb_buffer_pool_resize_status      |                                                  |
| Innodb_buffer_pool_pages_data         | 247                                              |
| Innodb_buffer_pool_bytes_data         | 4046848                                          |
| Innodb_buffer_pool_pages_dirty        | 0                                                |
| Innodb_buffer_pool_bytes_dirty        | 0                                                |
| Innodb_buffer_pool_pages_flushed      | 36                                               |
| Innodb_buffer_pool_pages_free         | 7945                                             |
| Innodb_buffer_pool_pages_misc         | 0                                                |
| Innodb_buffer_pool_pages_total        | 8192                                             |
| Innodb_buffer_pool_read_ahead_rnd     | 0                                                |
| Innodb_buffer_pool_read_ahead         | 0                                                |
| Innodb_buffer_pool_read_ahead_evicted | 0                                                |
| Innodb_buffer_pool_read_requests      | 1090                                             |
| Innodb_buffer_pool_reads              | 214                                              |
| Innodb_buffer_pool_wait_free          | 0                                                |
| Innodb_buffer_pool_write_requests     | 325                                              |
+---------------------------------------+--------------------------------------------------+
18 rows in set (0.01 sec)

mysql>

您可以Innodb_buffer_pool_pages_dirty使用

mysql> SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool_pages_dirty%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Innodb_buffer_pool_pages_dirty | 0     |
+--------------------------------+-------+
1 row in set (0.00 sec)

mysql>

這個數字可能會隨著頁面被刷新和頁面進入而波動,但這肯定會阻礙 InnoDB。您的解決方案只是增加緩衝池的大小。

我之前談到過其他不良影響(請參閱我的文章,當 InnoDB 日誌空間太小時會發生什麼情況

我想我見過這樣的案例

  • buffer_pool 設置得非常低(遠小於 128M)
  • 交易很複雜,不僅僅是“大”。
  • 錯誤表明 buffer_pool 空間不足(或類似情況)。您正在檢查錯誤,是嗎?

“大”不是問題——InnoDB 被設計用來處理任意多的行ROLLBACK,等等。但它必須更加努力——在完成查詢之前刷新臟頁,在表中儲存撤消的東西,而不僅僅是撤消日誌等

“複雜”可能是一個問題——假設它需要在幾個表及其索引的幾個 BTree 中鎖定很多塊。

我認為我沒有看到 128M 遇到麻煩(除了速度很慢)。我認為以前的預設值(8M)確實造成了麻煩。那是在 MyISAM 為王的時代,而 InnoDB 是新的羽翼未豐。

把它想像成一頓 5 道菜的大餐。廚房可以一次準備一道菜。但是,如果您要求同時傳遞所有 5 個呢?

引用自:https://dba.stackexchange.com/questions/249575