mysqlslap源码阅读

目录

1、看源码动力

2、mysqlslap简介

3、8.0版本官方链接

 4、mysqlslap执行的流程图

5、MAIN函数

6、concurrency_loop函数

7、run_statements函数

8、run_scheduler函数

9、run_task函数

10、run_query函数



1、看源码动力

        平时工作中,经常要模拟高并发场景对MYSQL进行压测,比如轮询2W个不同用户模拟登录。因为mysqlslap不支持SQL传参,这个时候可以选择使用JEMETER工具,但这个工具太重了。所以这个时候最好选择是自己编写程序进行压测。怎么写个小巧性能又好的工具,mysqlslap是个很好的参考。

2、mysqlslap简介

        mysqlslap is a diagnostic program designed to emulate client load for a MySQL server and to report the timing of each stage. It works as if multiple clients are accessing the server.

3、8.0版本官方链接

        MySQL :: MySQL 8.0 Reference Manual :: 4.5.8 mysqlslap — A Load Emulation Client

 4、mysqlslap执行的流程图

5、MAIN函数

循环的嵌套关系是:

        1、按engine_options列表循环

        2、接着按concurrency列表循环

        3、调用函数concurrency_loop

int main(int argc, char **argv) {
  MYSQL mysql{};
  ……
  mysql_init(&mysql);
  ……
  mysql_options(&mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
                &opt_zstd_compress_level);

  ……
  set_sql_mode(&mysql);
  //对锁counter_mutex、sleeper_mutex,条件变量count_threshold、sleep_threshold进行初始化
  native_mutex_init(&counter_mutex, nullptr);
  native_cond_init(&count_threshold);
  native_mutex_init(&sleeper_mutex, nullptr);
  native_cond_init(&sleep_threshold);

  /* Main iterations loop */
  //循环的嵌套关系是:
  //1、按engine_options列表循环
  //2、接着按concurrency列表循环
  eptr = engine_options;
  do {
    /* For the final stage we run whatever queries we were asked to run */
    uint *current;

    if (verbose >= 2) printf("Starting Concurrency Test\n");

    if (*concurrency) {
      for (current = concurrency; current && *current; current++)
        concurrency_loop(&mysql, *current, eptr);
    } else {
      uint infinite = 1;
      do {
        concurrency_loop(&mysql, infinite, eptr);
      } while (infinite++);
    }

    if (!opt_preserve) drop_schema(&mysql, create_schema_string);

  } while (eptr ? (eptr = eptr->next) : nullptr);

  native_mutex_destroy(&counter_mutex);
  native_cond_destroy(&count_threshold);
  native_mutex_destroy(&sleeper_mutex);
  native_cond_destroy(&sleep_threshold);

  mysql_close(&mysql); /* Close & free connection */

  ……

  return EXIT_SUCCESS;
}

6、concurrency_loop函数

循环iterations次调用run_scheduler函数

void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) {
  ……
  //循环嵌套关系
  //1、循环iterations次
  for (x = 0, sptr = head_sptr; x < iterations; x++, sptr++) {
    ……
    run_scheduler(sptr, query_statements, current, client_limit);
    if (post_statements) run_statements(mysql, post_statements);
    ……
  }
  ……
  //打印日志
  generate_stats(&conclusion, eptr, head_sptr);

  if (!opt_silent) print_conclusions(&conclusion);
  if (opt_csv_str) print_conclusions_csv(&conclusion);

  my_free(head_sptr);
}

7、run_statements函数

遍stmt中所有SQL,依次执行

static int run_statements(MYSQL *mysql, statement *stmt) {
  statement *ptr;
  MYSQL_RES *result;
  DBUG_TRACE;

  for (ptr = stmt; ptr && ptr->length; ptr = ptr->next) {
    if (run_query(mysql, ptr->string, ptr->length)) {
      fprintf(stderr, "%s: Cannot run query %.*s ERROR : %s\n", my_progname,
              (uint)ptr->length, ptr->string, mysql_error(mysql));
      exit(1);
    }
    if (mysql_field_count(mysql)) {
      result = mysql_store_result(mysql);
      mysql_free_result(result);
    }
  }

  return 0;
}

8、run_scheduler函数

启动concur个线程,线程函数为run_task

static int run_scheduler(stats *sptr, statement *stmts, uint concur,
                         ulonglong limit) {
  ……
  native_mutex_lock(&counter_mutex);
  thread_counter = 0;

  native_mutex_lock(&sleeper_mutex);
  master_wakeup = 1;
  native_mutex_unlock(&sleeper_mutex);
  //启动concur个线程
  for (x = 0; x < concur; x++) {
    /* now you create the thread */
    if (my_thread_create(&mainthread, &attr, run_task, (void *)&con) != 0) {
      fprintf(stderr, "%s: Could not create thread\n", my_progname);
      exit(0);
    }
    thread_counter++;
  }
  native_mutex_unlock(&counter_mutex);
  my_thread_attr_destroy(&attr);
  ……

  /*
    We loop until we know that all children have cleaned up.
  */
  ……

  return 0;
}

9、run_task函数

使用goto语句循环queries次执行runquery函数

extern "C" void *run_task(void *p) {
  ……

  {
    ……

    if (mysql_thread_init()) {
      fprintf(stderr, "%s: mysql_thread_init() failed ERROR : %s\n",
              my_progname, mysql_error(mysql));
      mysql_close(mysql);
      exit(0);
    }

    ……

    if (!opt_only_print) {
      if (slap_connect(mysql)) goto end;
    }

    ……
  limit_not_met:
    for (ptr = con->stmt, detach_counter = 0; ptr && ptr->length;
         ptr = ptr->next, detach_counter++) {
      ……
          if (run_query(mysql, buffer, length)) {
            ……

      //遍历查询结果
      ……
      queries++;
      ……
      //居然使用goto语句来循环queries次数!!!

      if (con->limit && queries == con->limit) goto end;
    }

    if (con->limit && queries < con->limit) goto limit_not_met;

  end:
    if (commit_rate) run_query(mysql, "COMMIT", strlen("COMMIT"));

    ……
}

10、run_query函数

static int run_query(MYSQL *mysql, const char *query, size_t len) {
  if (opt_only_print) {
    printf("%.*s;\n", (int)len, query);
    return 0;
  }

  if (verbose >= 3) printf("%.*s;\n", (int)len, query);
  return mysql_real_query(mysql, query, (ulong)len);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值