The document describes how the "show engine innodb status" command works internally in InnoDB. It outputs status information in several sections, including the timestamp, statistics calculated over the last few seconds, information on semaphores including counts and waits, transaction information including IDs and locks, and a list of current transactions. The information is generated by calling various InnoDB functions that retrieve status data from InnoDB internal structures.
Role Of Transgenic Animal In Target Validation-1.pptx
Show innodb status
1. mysql> show engine innodb status 这个命令在innodb内部是如何处理的? srv_printf_innodb_monitor调用处理所有全部信息的打印工作
2. ===================================== 100908 14:45:53 INNODB MONITOR OUTPUT ===================================== Per second averages calculated from the last 47 seconds 这个是输出的第一部分 100908 14:45:53 这个是时间戳,由ut_print_timestamp调用生成 (innobase/ut/ut0ut.c) code: fprintf(file,"%02d%02d%02d %2d:%02d:%02d", cal_tm_ptr->tm_year % 100, cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, cal_tm_ptr->tm_hour, cal_tm_ptr->tm_min, cal_tm_ptr->tm_sec);
3. 输出的第二部分 Per second averages calculated from the last 47 seconds Code: srv_printf_innodb_monitor current_time = time(NULL); time_elapsed = difftime(current_time, srv_last_monitor_time) + 0.001; srv_last_monitor_time = time(NULL); fprintf(file, " INNODB MONITOR OUTPUT" "=====================================" "Per second averages calculated from the last %lu seconds", (ulong)time_elapsed); 这里time_elapsed是两次运行show engine innodb status命令的时间差,或者....
11. code: os_event_wait_low 一直测试是否等待的事件被 set ,或者有信号发送,也就是说 thread 会阻塞在这里,直到条件满足才会返回,来执行释放 cell 的调用 for (;;) { if (event->is_set == TRUE || event->signal_count != old_signal_count) { os_fast_mutex_unlock(&(event->os_mutex)); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { os_thread_exit(NULL); } /* Ok, we may return */ return; } pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); }
12. 那么其他两个调用也是一样的情况 当并发两比较大的时候wait array 有可见的被使用的cell,这时,输出可以看到这些被使用的cell的细节 --Thread 1152170336 has waited at ./../include/buf0buf.ic line 630 for 0.00 seconds the semaphore: 6 Mutex at 0x2a957858b8 created file buf0buf.c line 517, lock var 0 7 waiters flag 0 8 wait is ending Code sync_array_output_info i = 0; count = 0; while (count < arr->n_reserved) { cell = sync_array_get_nth_cell(arr, i); if (cell->wait_object != NULL) { count++; sync_array_cell_print(file, cell); } i++; }
13. code sync_array_cell_print fprintf(file, "--Thread %lu has waited at %s line %lu" " for %.2f seconds the semaphore:", (ulong) os_thread_pf(cell->thread), cell->file, (ulong) cell->line, difftime(time(NULL), cell->reservation_time)); 那么第1个是thread id,第2,3个参数是申请锁的位置,第4个是保留这个cell的时间,也就是距离申请wait array cell的时间 fprintf(file, "Mutex at %p created file %s line %lu, lock var %lu" "waiters flag %lu", (void*) mutex, mutex->cfile_name, (ulong) mutex->cline, (ulong) mutex->lock_word,(ulong) mutex->waiters); 第1个参数mutex的内存位置,第2,3个参数为mutex创建的位置,第4个参数是test and set原子操作的目标值,第5个参数为是否有threads在mutex上等待(1为有threads等待)
15. 事务部分 ------------ TRANSACTIONS ------------ Trx id counter 0 48406123 Purge done for trx's n:o < 0 48406107 undo n:o < 0 0 History list length 16 Total number of lock structs in row lock hash table 0 LIST OF TRANSACTIONS FOR EACH SESSION: ---TRANSACTION 0 0, not started, process no 24942, OS thread id 1175292224 MySQL thread id 1193, query id 28543840 localhost root show engine innodb status ---TRANSACTION 0 48406039, not started, process no 24942, OS thread id 107810643 2 MySQL thread id 1190, query id 28543359 172.16.16.14 ecp ...... MySQL thread id 25, query id 28543836 Has read all relay log; waiting for the slave I/O thread to update it
16. Trx id counter 0 48406123 Purge done for trx's n:o < 0 48406107 undo n:o < 0 0 History list length 16 Total number of lock structs in row lock hash table 0 Code lock_print_info_summary fputs("------------" "TRANSACTIONS" "------------", file); fprintf(file, "Trx id counter %lu %lu", (ulong) ut_dulint_get_high(trx_sys->max_trx_id), (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); 第 1 行显示的是未分配事务号,也就是即将分配给下一个新事务的事务号。 事务系统结构 (trx_sys) 中的 max_trx_id 是个 double unsigned long int (64 位 ) 这里分别打印高 32 位值和低 32 位值
17. Code fprintf(file, "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu", (ulong) ut_dulint_get_high(purge_sys->purge_trx_no), (ulong) ut_dulint_get_low(purge_sys->purge_trx_no), (ulong) ut_dulint_get_high(purge_sys->purge_undo_no), (ulong) ut_dulint_get_low(purge_sys->purge_undo_no)); 这里打印的是purge系统的指针信息,第1个是所有id小于purge_trx_no的事务都已经被清理。第2个是所有undo no小于purge_undo_no的undo 记录都已经被清理,同样这2个值 都是double unsigned long int类型
18. Code fprintf(file, "History list length %lu", (ulong) trx_sys->rseg_history_len); 这部分打印 history list 的长度,那么 history list 是什么,打个比方来说 history list 就是个存放垃圾的垃圾场,那么垃圾是什么,垃圾就是已经提交,并且有对记录做改动的事务,也就是产生 undo log 的事务 , 而清洁工就是 purge thread, 当它清理完一个事务的时候就减少 history list 的长度,而当有新的更新事务提交的时候这个垃圾场的垃圾量 (history list length) 就增加
19. Code fprintf(file, "Total number of lock structs in row lock hash table %lu", (ulong) lock_get_n_rec_locks()); lock_get_n_rec_locks(void) { lock_t* lock; ulint n_locks = 0; ulint i; ut_ad(mutex_own(&kernel_mutex)); for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) { lock = HASH_GET_FIRST(lock_sys->rec_hash, i); while (lock) { n_locks++; lock = HASH_GET_NEXT(hash, lock); } } return(n_locks); }
21. 接下来的部分是打印目前执行事务的具体信息 Code lock_print_info_all_transactions fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:"); trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); while (trx) { if (trx->conc_state == TRX_NOT_STARTED) { fputs("---", file); trx_print(file, trx, 600); } trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); } 首先打印的是未开始的事务,具体打印代码在 trx_print 调用中
22. ---TRANSACTION 0 48412790 , not started, process no 24942 , OS thread id 1078106432 Code t rx_print fprintf(f, "TRANSACTION %lu %lu", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id)); switch (trx->conc_state) { case TRX_NOT_STARTED: fputs(", not started", f); Break; ...... fprintf(f, ", process no %lu", trx->mysql_process_no); fprintf(f, ", OS thread id %lu", (ulong) os_thread_pf(trx->mysql_thread_id)); 第一个参数为事务 id, 第 2 个参数为 mysql 进程 id, 第 3 个为该事务的 OS 线程 id (??)
23. MySQL thread id 1190 , query id 28655384 172.16.16.14 ecp Code innobase_mysql_print_thd fputs(thd_security_context(thd, buffer, sizeof(buffer), max_query_len), f); thd_security_context len= my_snprintf(header, sizeof(header), "MySQL thread id %lu, query id %lu", thd->thread_id, (ulong) thd->query_id); 第 1 个参数是 mysql 线程 id, 第 2 个参数是查询 id, 后面的是访问信息