Buffer blocks에 있는 list의 종류에는 3가지가 있다.
이해한대로 적어보겠다.
Foreground 유저가 read(Pa)라는 요청을 보냈지만 Pa가 buffer pool에 없는 상태이기 때문에 buffer miss가 발생했다.
먼저 바로 사용할 수 있는 free list를 찾는다. 하지만 free list가 없는 상태이다.
다음 후보인 clean page를 찾기 위해 LRU list의 tail부터 본다. clean page를 찾는 이유는, dirty page를 사용하려면 Disk로 추가적인 I/O를 해야하기 때문이다.(dirty page는 write된 정보가 disk에 반영되지 않은 상태이기 때문)
설정한 LRU scan depth안에 clean page가 없다면 가장 마지막에 있는 Dirty page를 Disk에 write한 후(flush) Disk에서 요청한 Pa를 read해 transaction이 끝난다. 맨 끝 page를 flush하는 이유는 LRU policy에 의해 마지막 page가 제일 쓰이지 않은 page이기 때문이다.
Dirty page를 직접 flush하는 것은 Disk I/O가 필요해 시간이 많이 걸리므로, page cleaner thread가 만들어주는 free block을 사용하는 방법도 있다.이 과정도 이해한대로 작성해보겠다.
Page cleaner thread가 LRU list에 있는 dirty page를 초 단위로 Disk에 asynchronous write한다 (flush). (buffer pool과 Disk는 서로의 상태를 모르기 때문에 (synchronize하기 않기 때문에) asynchronous wirte라고 한거같다).
dirty page의 양은 innodb_lru_scan_depth로 설정할 수 있다.
이렇게 free buffer frame이 생기게 되고, 이 free buffer frame을 Free list에 붙인다. 이로써 Foreground user는 free list를 사용할 수 있게 된다. 반면에 Background writer는 asynchronous하게 free buffer를 만든다.
InnoDB Architecture를 살펴보면 Buffer Manager는 buf 폴더에 위치한다.
Buffer Flusher (buf0flu.cc) : dirty page flusher
Doublewrite (buf0dblwr.cc) : double write buffer (durability를 위해 double write한다.)
Buffer Pool (buf0buf.cc) : buffer pool manager
실제 코드를 보면, buffer pool에 Flush list, free list, LRU list가 구현돼있는 것을 볼 수 있다.
Buffer Read (buf0read.cc) : read buffer
LRU (buf0lru.cc) : buffer replacement
위에서, buffer miss 동안에 free buffer frame을 return하는 과정을 살펴봤다. 이 과정을 담고있는 실제 코드의 buf_LRU_get_free_block() 함수를 살펴보자. free buffer를 얻을 때까지 loop를 돈다. mutex를 먼저 get한 후, free block이 있는지 본다. 있다면 block != NULL 이므로 if문에 들어가고 그 block을 return한다. free block을 찾지 못하면 Step2로 간다.
step2에서는 free block을 찾지 못한 상태이므로, LRU list의 tail부터 clean page를 찾고 free the according buffer frame한다. 즉 그 buffer frame을 free list로 보내는 것이다. buffer free 후에 step1의 loop에 다시 들어가고, 그 block을 return한다.
이 부분은 page cleaner thread가 background에서 돌아가면서 dirty page를 flush할 수도 있기 때문에 그 기회를 기다리는 것이다.
위 과정으로 flush되지 않는다면 LRU tail에 있는 single dirty page를 victim으로 선정해 flush해준다. dirty page를 flush하려면 Disk I/O를 해야하기 때문에 Step1 or Step2 보다 많은 시간을 잡아먹는다.
Reference
https://www.slideshare.net/meeeejin/mysql-buffer-management