本文为随笔。留个接口后面好详细学习。
函数接口 buf_LRU_flush_or_remove_pages 用于确认是否维护 LRU list,其中有三种类型:
/** Algorithm to remove the pages for a tablespace from the buffer pool.
See buf_LRU_flush_or_remove_pages(). */
enum buf_remove_t {
BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer
pool, don't write or sync to disk */
BUF_REMOVE_FLUSH_NO_WRITE, /*!< Remove only, from the flush list,
don't write or sync to disk */
BUF_REMOVE_FLUSH_WRITE /*!< Flush dirty pages to disk only
don't remove from the buffer pool */
};
- drop为:BUF_REMOVE_FLUSH_NO_WRITE,需要维护flush list,不回写数据
- trunacte为:BUF_REMOVE_ALL_NO_WRITE,需要维护flush list和lru list,不回写数据
下面是buf_LRU_flush_or_remove_pages函数这里的cascade判断:
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
switch (buf_remove) {
case BUF_REMOVE_ALL_NO_WRITE:
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
break; //维护LRU
case BUF_REMOVE_FLUSH_NO_WRITE:
/* It is a DROP TABLE for a single table
tablespace. No AHI entries exist because
we already dealt with them when freeing up
extents. */
case BUF_REMOVE_FLUSH_WRITE:
/* We allow read-only queries against the
table, there is no need to drop the AHI entries. */
break;
}
下面可以看到
DROP调用:
(gdb) bt
#0 buf_LRU_flush_or_remove_pages (id=145, buf_remove=BUF_REMOVE_FLUSH_NO_WRITE, trx=0x0)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/buf/buf0lru.cc:986
#1 0x0000000001d10eff in fil_delete_tablespace (id=145, buf_remove=BUF_REMOVE_FLUSH_NO_WRITE)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/fil/fil0fil.cc:2825
#2 0x0000000001b40c8a in row_drop_single_table_tablespace (space_id=145, tablename=0x7ffe44071170 "test/tfl", filepath=0x7ffe4405c4f8 "./test/tfl.ibd",
is_temp=false, is_encrypted=false, trx=0x7fffd78045f0) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0mysql.cc:4742
#3 0x0000000001b421a3 in row_drop_table_for_mysql (name=0x7ffef07f9370 "test/tfl", trx=0x7fffd78045f0, drop_db=false, nonatomic=true, handler=0x0)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0mysql.cc:5311
#4 0x00000000019dc60f in ha_innobase::delete_table (this=0x7ffe44006cf8, name=0x7ffef07fa7e0 "./test/tfl")
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:13545
#5 0x0000000000f8934c in handler::ha_delete_table (this=0x7ffe44006cf8, name=0x7ffef07fa7e0 "./test/tfl")
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/handler.cc:5240
#6 0x0000000000f82272 in ha_delete_table (thd=0x7ffe44000b70, table_type=0x2f2c420, path=0x7ffef07fa7e0 "./test/tfl", db=0x7ffe44006b00 "test",
alias=0x7ffe44006540 "tfl", generate_warning=true) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/handler.cc:2763
#7 0x000000000165b291 in mysql_rm_table_no_locks (thd=0x7ffe44000b70, tables=0x7ffe44006578, if_exists=false, drop_temporary=false, drop_view=false,
dont_log_query=false) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_table.cc:2680
#8 0x0000000001659f97 in mysql_rm_table (thd=0x7ffe44000b70, tables=0x7ffe44006578, if_exists=0 '\000', drop_temporary=0 '\000')
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_table.cc:2221
#9 0x00000000015cc9b4 in mysql_execute_command (thd=0x7ffe44000b70, first_level=true) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:3769
#10 0x00000000015d30c6 in mysql_parse (thd=0x7ffe44000b70, parser_state=0x7ffef07fc600) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:5901
#11 0x00000000015c6c5a in dispatch_command (thd=0x7ffe44000b70, com_data=0x7ffef07fcd70, command=COM_QUERY)
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1490
#12 0x00000000015c59e7 in do_command (thd=0x7ffe44000b70) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1021
#13 0x000000000170e660 in handle_connection (arg=0x5fa1fc0) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:312
#14 0x0000000001945620 in pfs_spawn_thread (arg=0x5f9bd00) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/perfschema/pfs.cc:2190
#15 0x00007ffff7bc6aa1 in start_thread () from /lib64/libpthread.so.0
#16 0x00007ffff6719bcd in clone () from /lib64/libc.so.6
TRUNACTE 调用:
(gdb) bt
#0 buf_LRU_flush_or_remove_pages (id=577, buf_remove=BUF_REMOVE_ALL_NO_WRITE, trx=0x0)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/buf/buf0lru.cc:986
#1 0x0000000001d117b1 in fil_reinit_space_header_for_table (table=0x7ffe80b5a920, size=6, trx=0x7fffd7804080)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/fil/fil0fil.cc:3030
#2 0x0000000001b859a0 in row_truncate_table_for_mysql (table=0x7ffe80b5a920, trx=0x7fffd7804080)
at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0trunc.cc:2071
#3 0x00000000019dc12e in ha_innobase::truncate (this=0x7ffe440cab50) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:13420
#4 0x0000000000f88bc5 in handler::ha_truncate (this=0x7ffe440cab50) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/handler.cc:4997
#5 0x000000000181aa78 in Sql_cmd_truncate_table::handler_truncate (this=0x7ffe44006b18, thd=0x7ffe44000b70, table_ref=0x7ffe44006588, is_tmp_table=false)
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_truncate.cc:244
#6 0x000000000181b348 in Sql_cmd_truncate_table::truncate_table (this=0x7ffe44006b18, thd=0x7ffe44000b70, table_ref=0x7ffe44006588)
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_truncate.cc:510
#7 0x000000000181b4b3 in Sql_cmd_truncate_table::execute (this=0x7ffe44006b18, thd=0x7ffe44000b70)
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_truncate.cc:566
#8 0x00000000015d0de6 in mysql_execute_command (thd=0x7ffe44000b70, first_level=true) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:5117
#9 0x00000000015d30c6 in mysql_parse (thd=0x7ffe44000b70, parser_state=0x7ffef07fc600) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:5901
#10 0x00000000015c6c5a in dispatch_command (thd=0x7ffe44000b70, com_data=0x7ffef07fcd70, command=COM_QUERY)
at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1490
#11 0x00000000015c59e7 in do_command (thd=0x7ffe44000b70) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1021
#12 0x000000000170e660 in handle_connection (arg=0x5fa1fc0) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:312
#13 0x0000000001945620 in pfs_spawn_thread (arg=0x5f9bd00) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/perfschema/pfs.cc:2190
#14 0x00007ffff7bc6aa1 in start_thread () from /lib64/libpthread.so.0
#15 0x00007ffff6719bcd in clone () from /lib64/libc.so.6
下面是源码truncate流程:
/* Understanding the truncate flow.
Step-1: Perform intiial sanity check to ensure table can be truncated.
This would include check for tablespace discard status, ibd file
missing, etc ....
Step-2: Start transaction (only for non-temp table as temp-table don't
modify any data on disk doesn't need transaction object).
Step-3: Validate ownership of needed locks (Exclusive lock).
Ownership will also ensure there is no active SQL queries, INSERT,
SELECT, .....
Step-4: Stop all the background process associated with table.
Step-5: There are few foreign key related constraint under which
we can't truncate table (due to referential integrity unless it is
turned off). Ensure this condition is satisfied.
Step-6: Truncate operation can be rolled back in case of error
till some point. Associate rollback segment to record undo log.
Step-7: Generate new table-id.
Why we need new table-id ?
Purge and rollback case: we assign a new table id for the table.
Since purge and rollback look for the table based on the table id,
they see the table as 'dropped' and discard their operations.
Step-8: Log information about tablespace which includes
table and index information. If there is a crash in the next step
then during recovery we will attempt to fixup the operation.
Step-9: Drop all indexes (this include freeing of the pages
associated with them).
Step-10: Re-create new indexes.
Step-11: Update new table-id to in-memory cache (dictionary),
on-disk (INNODB_SYS_TABLES). INNODB_SYS_INDEXES also needs to
be updated to reflect updated root-page-no of new index created
and updated table-id.
Step-12: Cleanup Stage. Reset auto-inc value to 1.
Release all the locks.
Commit the transaction. Update trx operation state.
Notes:
- On error, log checkpoint is done followed writing of magic number to
truncate log file. If servers crashes after truncate, fix-up action
will not be applied.
- log checkpoint is done before starting truncate table to ensure
that previous REDO log entries are not applied if current truncate
crashes. Consider following use-case:
- create table .... insert/load table .... truncate table (crash)
- on restart table is restored .... truncate table (crash)
- on restart (assuming default log checkpoint is not done) will have
2 REDO log entries for same table. (Note 2 REDO log entries
for different table is not an issue).
For system-tablespace we can't truncate the tablespace so we need
to initiate a local cleanup that involves dropping of indexes and
re-creating them. If we apply stale entry we might end-up issuing
drop on wrong indexes.
- Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE,
so we do not have to remove insert buffer records, as the
insert buffer works at a low level. If a freed page is later
reallocated, the allocator will remove the ibuf entries for
it. When we prepare to truncate *.ibd files, we remove all entries
for the table in the insert buffer tree. This is not strictly
necessary, but we can free up some space in the system tablespace.
- Linear readahead and random readahead: we use the same
method as in 3) to discard ongoing operations. (This is only
relevant for TRUNCATE TABLE by TRUNCATE TABLESPACE.)
Ensure that the table will be dropped by trx_rollback_active() in
case of a crash.
*/
下面两篇阿里内核月报,后期详细学习可以参考:
网友评论