1. 程式人生 > 其它 >MySQL根據5.1.34之前版本的一個BUG分析O_DIRECT

MySQL根據5.1.34之前版本的一個BUG分析O_DIRECT

Mysql錯誤日誌:

Version:  '5.1.34-percona-highperf-log'  socket:  '/home/mysql/mysql.sock'  port:  3306  Source distribution
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_191_0.ibd: CREATE: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_191_0.ibd: OPEN: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_192_0.ibd: CREATE: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_192_0.ibd: OPEN: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662

innodb_flush_method 這個引數控制著innodb資料檔案及redo log的開啟、刷寫模式。對於這個引數,文件上是這樣描述的:

從MySQL 5.6的版本開始,也就是InnoDB 1.2版本中(PS:MariaDB 10.x版本將整合InnoDB 1.2版本),對於引數innodb_flush_method提供了一個新的設定值O_DIRECT_NO_FSYNC。

有四個值:fdatasync,O_DSYNC,O_DIRECT,O_DIRECT_NO_FSYNC

  • 預設是fdatasync,呼叫fsync()去刷資料檔案與redo log的buffer
  • 為O_DSYNC時,innodb會使用O_SYNC方式開啟和刷寫redo log,使用fsync()刷寫資料檔案
  • 為O_DIRECT時,innodb使用O_DIRECT開啟資料檔案,使用fsync()刷寫資料檔案跟redo log
  • 為O_DIRECT_NO_FSYNC時,InnoDB儲存引擎將依然使用O_DIRECT選項開啟資料表空間檔案,但是在重新整理時,不再需要需要額外的fsync操作

首先檔案的寫操作包括三步:open,write,flush

  • 上面最常提到的fsync(int fd)函式,該函式作用是flush時將與fd檔案描述符所指檔案有關的buffer刷寫到磁碟,並且flush完元資料資訊(比如修改日期、建立日期等)才算flush成功。
  • 使用O_SYNC方式開啟redo檔案表示當write日誌時,資料都write到磁碟,並且元資料也需要更新,才返回成功
  • O_DIRECT則表示我們的write操作是從mysql innodb buffer裡直接向磁碟上寫

至此總結一下三者寫資料方式:

  • fdatasync模式:寫資料時,write這一步並不需要真正寫到磁碟才算完成(可能寫入到作業系統buffer中就會返回完成),真正完成是flush操作,buffer交給作業系統去flush,並且檔案的元資料資訊也都需要更新到磁碟。
  • O_DSYNC模式:寫日誌操作是在write這步完成,而資料檔案的寫入是在flush這步通過fsync完成
  • O_DIRECT模式:資料檔案的寫入操作是直接從mysql innodb buffer到磁碟的,並不用通過作業系統的緩衝,而真正的完成也是在flush這步,日誌還是要經過OS緩衝

優點:

  1. 目前都是硬碟如SSD、F/M卡 IO已經很快了,無需再利用系統快取。
  2. 最為安全和穩妥的做法還是將引數innodb_flush_method設定為O_DIRECT。
  3. 若重做日誌使用O_DIRECT,寫入重做日誌檔案的過程會變慢(因為不是僅寫入到作業系統快取),Group Commit的效率就會變差。