---
# System prepended metadata

title: thread buffer がいつ解放されるか

---

# thread buffer がいつ解放されるか？
## thread buffer の種類
- join_buffer
- sort_buffer
- tmp_table_size
- select_into_buffer_size

ref: https://gihyo.jp/article/2022/10/mysql-rcn0183

## sort_buffer

ここで止めてみる (Filesort_info class)
- https://github.com/mysql/mysql-server/blob/mysql-cluster-8.0.32/sql/sql_sort.h#L260

### backtrace

```
(gdb) bt
#0  Filesort_info::free_sort_buffer (this=0x7fdfe5092ae0) at /mysql-8.0.32/sql/sql_sort.h:260
#1  0x000055a0caf53a17 in SortingIterator::CleanupAfterQuery (this=0x7fdfe5092ab8) at /mysql-8.0.32/sql/iterators/sorting_iterator.cc:418
#2  0x000055a0caf53954 in SortingIterator::~SortingIterator (this=0x7fdfe5092ab8, __in_chrg=<optimized out>) at /mysql-8.0.32/sql/iterators/sorting_iterator.cc:414
#3  0x000055a0ca790fb2 in destroy<RowIterator> (ptr=0x7fdfe5092ab8) at /mysql-8.0.32/include/my_alloc.h:459
#4  0x000055a0ca790ef2 in Destroy_only<RowIterator>::operator() (this=0x7fdfe5092c18, ptr=0x7fdfe5092ab8) at /mysql-8.0.32/include/my_alloc.h:481
#5  0x000055a0ca790e14 in std::unique_ptr<RowIterator, Destroy_only<RowIterator> >::~unique_ptr (this=0x7fdfe5092c18, __in_chrg=<optimized out>) at /usr/include/c++/11/bits/unique_ptr.h:361
#6  0x000055a0caf7ac92 in LimitOffsetIterator::~LimitOffsetIterator (this=0x7fdfe5092c08, __in_chrg=<optimized out>) at /mysql-8.0.32/sql/iterators/composite_iterators.h:106
#7  0x000055a0ca790fb2 in destroy<RowIterator> (ptr=0x7fdfe5092c08) at /mysql-8.0.32/include/my_alloc.h:459
#8  0x000055a0ca790ef2 in Destroy_only<RowIterator>::operator() (this=0x7fdfe507fc48, ptr=0x7fdfe5092c08) at /mysql-8.0.32/include/my_alloc.h:481
#9  0x000055a0ca8f1d86 in std::__uniq_ptr_impl<RowIterator, Destroy_only<RowIterator> >::reset (this=0x7fdfe507fc48, __p=0x0) at /usr/include/c++/11/bits/unique_ptr.h:182
#10 0x000055a0ca995cdb in std::unique_ptr<RowIterator, Destroy_only<RowIterator> >::reset (this=0x7fdfe507fc48, __p=0x0) at /usr/include/c++/11/bits/unique_ptr.h:456
#11 0x000055a0caaaad8f in Query_expression::cleanup (this=0x7fdfe507fc10, full=true) at /mysql-8.0.32/sql/sql_union.cc:1841
#12 0x000055a0ca812c25 in LEX::cleanup (this=0x7fdff01379d0, full=true) at /mysql-8.0.32/sql/sql_lex.h:4072
#13 0x000055a0ca95d750 in mysql_execute_command (thd=0x7fdff0acb960, first_level=true) at /mysql-8.0.32/sql/sql_parse.cc:4907
#14 0x000055a0ca95ecaa in dispatch_sql_command (thd=0x7fdff0acb960, parser_state=0x7fe0647f79f0) at /mysql-8.0.32/sql/sql_parse.cc:5322
#15 0x000055a0ca95433d in dispatch_command (thd=0x7fdff0acb960, com_data=0x7fe0647f8340, command=COM_QUERY) at /mysql-8.0.32/sql/sql_parse.cc:2036
#16 0x000055a0ca9522eb in do_command (thd=0x7fdff0acb960) at /mysql-8.0.32/sql/sql_parse.cc:1439
#17 0x000055a0cab9eaa9 in handle_connection (arg=0x55a0d362bf20) at /mysql-8.0.32/sql/conn_handler/connection_handler_per_thread.cc:302
#18 0x000055a0ccb7aeae in pfs_spawn_thread (arg=0x55a0d3636760) at /mysql-8.0.32/storage/perfschema/pfs.cc:2986
#19 0x00007fe0b1c09ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#20 0x00007fe0b1c9b850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
```

次の step 

```
(gdb) s
Filesort_buffer::free_sort_buffer (this=0x7fdfe5092ae0) at /mysql-8.0.32/sql/filesort_utils.cc:414
414     void Filesort_buffer::free_sort_buffer() {
```

filesort_buffer class
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/filesort_utils.h#L80

の、free_sort_buffer 関数に飛ぶ
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/filesort_utils.cc#L414


backtrace を辿っていくと、[my_alloc.h:459](https://github.com/mysql/mysql-server/blob/mysql-8.0.32/include/my_alloc.h#L459) がわからない


sql/sql_lex.h:4072 の cleanup() 関数で呼ばれてるのでクエリ実行後？
cleanup 関数のコメントは以下
```cpp
  /**
    Cleanup this subtree (this Query_block and all nested Query_blockes and
    Query_expressions).
    @param full  if false only partial cleanup is done, JOINs and JOIN_TABs are
    kept to provide info for EXPLAIN CONNECTION; if true, complete cleanup is
    done, all JOINs are freed.
  */
  void cleanup(bool full) override;
```

mysql の query 実行関数は mysql_execute_command()?
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/sql_parse.cc#L2915

→実際に実行されるのはここっぽい？ (mysql_sql_stmt_execute()?)
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/sql_prepare.cc#L1942

mysql_execute_command() から cleanup() が呼ばれてる
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/sql_parse.cc#L4907


## 2/6

実行したクエリ
```
SELECT * FROM employeess ORDER BY birth_date LIMIT 3
```

.h のファイルにはブレークポイントを置けないっぽい？ので [/mysql-8.0.32/sql/sql_union.cc:1841](https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/sql_union.cc#L1841) にブレークポイントを置いてステップ実行していく
← .h はヘッダファイル（クラスの型定義とか）、.cpp はソースファイル（ヘッダファイルで定義された型に対する実際の実装）

ここでの this は [Query_expression](https://dev.mysql.com/doc/dev/mysql-server/latest/classQuery__expression.html).

gdb 上で `print this.query_term` とかやってみたらクエリの中身見れるのかと思ったら、そんなことはなかった

次に step 実行したら `std::unique_ptr::reset()` に辿り着く
https://cpprefjp.github.io/reference/memory/unique_ptr/reset.html
← 引数を与えない場合、ポインタから値を開放して、該当ポインタが何も指していない状態になる

20回ぐらい step 実行したら [/mysql-8.0.32/include/my_alloc.h:481](https://github.com/mysql/mysql-server/blob/mysql-8.0.32/include/my_alloc.h#L481) に辿り着く

```
(gdb) print ptr
$1 = (RowIterator *) 0xfffebcad91b8
```

ptr は [RowIterator](https://dev.mysql.com/doc/dev/mysql-server/latest/classRowIterator.html) というクラスのものらしい

Detailed description によれば、選択された取得方法を使用して、テーブルから１行ずつレコードを読み取る単純なイテレータらしい。

なんだか THD が取れる。

```
(gdb) print ptr.thd
$2 = {THD *(const RowIterator * const)} 0xaaaac01a56cc <RowIterator::thd() const>
```

次に step 実行したら、[my_alloc.h:459](https://github.com/mysql/mysql-server/blob/mysql-8.0.32/include/my_alloc.h#L459) に辿り着く

ptr は先ほどの RowIterator なので、RowIterator の destructor が呼ばれている。
→
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/iterators/row_iterator.h#L86

```c++
class RowIterator {
 public:
  // NOTE: Iterators should typically be instantiated using NewIterator,
  // in sql/iterators/timing_iterator.h.
  explicit RowIterator(THD *thd) : m_thd(thd) {}
  virtual ~RowIterator() = default;
```

virtual って何！？ default って何！？
https://cpprefjp.github.io/lang/cpp11/defaulted_and_deleted_functions.html

デフォルトの動作が定義されていて、特殊なメンバ関数に対してのみ代入できる感じっぽい

https://yohe.gitbooks.io/cpp-14/content/chapter_1/core/explicit_default_func.html

destructor は default を指定すると空の関数になると書いてある...

次の step 実行→ [/mysql-8.0.32/sql/iterators/composite_iterators.h:106](https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/iterators/composite_iterators.h#L106)

```c++
LimitOffsetIterator::~LimitOffsetIterator (this=0xfffebcad91b8, __in_chrg=<optimized out>) at /mysql-8.0.32/sql/iterators/composite_iterators.h:106

class LimitOffsetIterator final : public RowIterator {
```

RowIterator を継承した LimitOffsetIterator の方に処理が移った

次の step 実行

```c++
(gdb) s
std::unique_ptr<RowIterator, Destroy_only<RowIterator> >::~unique_ptr (this=0xfffebcad91c8, __in_chrg=<optimized out>) at /usr/include/c++/11/bits/unique_ptr.h:359
359             auto& __ptr = _M_t._M_ptr();

```
c++ の標準ライブラリを抜けると、次の step 実行

```c++
(gdb) s
Destroy_only<RowIterator>::operator() (this=0xfffebcad91c8, ptr=0xfffebcad9068) at /mysql-8.0.32/include/my_alloc.h:481
481         destroy(ptr);
(gdb) s
destroy<RowIterator> (ptr=0xfffebcad9068) at /mysql-8.0.32/include/my_alloc.h:459
459       if (ptr != nullptr) ptr->~T();
(gdb) print ptr
$5 = (RowIterator *) 0xfffebcad9068
(gdb) s
SortingIterator::~SortingIterator (this=0xfffebcad9068, __in_chrg=<optimized out>) at /mysql-8.0.32/sql/iterators/sorting_iterator.cc:412
412     SortingIterator::~SortingIterator() {
(gdb)
```

[SortingIterator](https://dev.mysql.com/doc/dev/mysql-server/latest/classSortingIterator.html) の destructor に辿り着いた
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/iterators/sorting_iterator.cc#L412

```c++
SortingIterator::~SortingIterator() {
  ReleaseBuffers();
  CleanupAfterQuery();
}
```

step 実行、当然 ReleaseBuffers() の中に入る

```c++
(gdb) s
413       ReleaseBuffers();
(gdb) s
SortingIterator::ReleaseBuffers (this=0xfffebcad9068) at /mysql-8.0.32/sql/iterators/sorting_iterator.cc:425
425       m_result_iterator.reset();
(gdb)
```

https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/iterators/sorting_iterator.cc#L424

かなりここっぽい... my_free() してるし...

- m_result_iterator
- m_sort_result.io_cache

の二つがどういう意味なのか調べるところから　