1
/* Copyright (C) 2004 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; either version 2 of the License, or
6
(at your option) any later version.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program; if not, write to the Free Software
15
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include "db_driver.h"
26
#define GET_RANDOM_ID() ((*rnd_func)())
28
/* How many rows to insert in a single query (used for test DB creation) */
29
#define INSERT_ROWS 10000
31
/* How many rows to insert before COMMITs (used for test DB creation) */
32
#define ROWS_BEFORE_COMMIT 1000
34
/* Maximum query length */
35
#define MAX_QUERY_LEN 1024
37
/* Large prime number to generate unique set of random numbers in delete test */
38
#define LARGE_PRIME 2147483647
40
/* Command line arguments definition */
41
static sb_arg_t oltp_args[] =
43
{"oltp-test-mode", "test type to use {simple,complex,nontrx,sp}", SB_ARG_TYPE_STRING, "complex"},
44
{"oltp-sp-name", "name of store procedure to call in SP test mode", SB_ARG_TYPE_STRING, ""},
45
{"oltp-read-only", "generate only 'read' queries (do not modify database)", SB_ARG_TYPE_FLAG, "off"},
46
{"oltp-skip-trx", "skip BEGIN/COMMIT statements", SB_ARG_TYPE_FLAG, "off"},
47
{"oltp-range-size", "range size for range queries", SB_ARG_TYPE_INT, "100"},
48
{"oltp-point-selects", "number of point selects", SB_ARG_TYPE_INT, "10"},
49
{"oltp-simple-ranges", "number of simple ranges", SB_ARG_TYPE_INT, "1"},
50
{"oltp-sum-ranges", "number of sum ranges", SB_ARG_TYPE_INT, "1"},
51
{"oltp-order-ranges", "number of ordered ranges", SB_ARG_TYPE_INT, "1"},
52
{"oltp-distinct-ranges", "number of distinct ranges", SB_ARG_TYPE_INT, "1"},
53
{"oltp-index-updates", "number of index update", SB_ARG_TYPE_INT, "1"},
54
{"oltp-non-index-updates", "number of non-index updates", SB_ARG_TYPE_INT, "1"},
56
"mode for non-transactional test {select, update_key, update_nokey, insert, delete}",
57
SB_ARG_TYPE_STRING, "select"},
58
{"oltp-auto-inc", "whether AUTO_INCREMENT (or equivalent) should be used on id column",
59
SB_ARG_TYPE_FLAG, "on"},
60
{"oltp-connect-delay", "time in microseconds to sleep after connection to database", SB_ARG_TYPE_INT,
62
{"oltp-user-delay-min", "minimum time in microseconds to sleep after each request",
63
SB_ARG_TYPE_INT, "0"},
64
{"oltp-user-delay-max", "maximum time in microseconds to sleep after each request",
65
SB_ARG_TYPE_INT, "0"},
66
{"oltp-table-name", "name of test table", SB_ARG_TYPE_STRING, "sbtest"},
67
{"oltp-table-size", "number of records in test table", SB_ARG_TYPE_INT, "10000"},
69
{"oltp-dist-type", "random numbers distribution {uniform,gaussian,special}", SB_ARG_TYPE_STRING,
71
{"oltp-dist-iter", "number of iterations used for numbers generation", SB_ARG_TYPE_INT, "12"},
72
{"oltp-dist-pct", "percentage of values to be treated as 'special' (for special distribution)",
73
SB_ARG_TYPE_INT, "1"},
74
{"oltp-dist-res", "percentage of 'special' values to use (for special distribution)",
75
SB_ARG_TYPE_INT, "75"},
77
{NULL, NULL, SB_ARG_TYPE_NULL, NULL}
89
/* Modes for 'non-transactional' test */
93
NONTRX_MODE_UPDATE_KEY,
94
NONTRX_MODE_UPDATE_NOKEY,
99
/* Random numbers distributions */
109
oltp_mode_t test_mode;
110
unsigned int read_only;
111
unsigned int skip_trx;
112
unsigned int auto_inc;
113
unsigned int range_size;
114
unsigned int point_selects;
115
unsigned int simple_ranges;
116
unsigned int sum_ranges;
117
unsigned int order_ranges;
118
unsigned int distinct_ranges;
119
unsigned int index_updates;
120
unsigned int non_index_updates;
121
nontrx_mode_t nontrx_mode;
122
unsigned int connect_delay;
123
unsigned int user_delay_min;
124
unsigned int user_delay_max;
127
unsigned int table_size;
128
oltp_dist_t dist_type;
129
unsigned int dist_iter;
130
unsigned int dist_pct;
131
unsigned int dist_res;
134
/* Test statements structure */
142
db_stmt_t *range_sum;
143
db_stmt_t *range_order;
144
db_stmt_t *range_distinct;
145
db_stmt_t *update_index;
146
db_stmt_t *update_non_index;
151
/* Bind buffers for statements */
154
sb_sql_query_point_t point;
155
sb_sql_query_range_t range;
156
sb_sql_query_range_t range_sum;
157
sb_sql_query_range_t range_order;
158
sb_sql_query_range_t range_distinct;
159
sb_sql_query_update_t update_index;
160
sb_sql_query_update_t update_non_index;
161
sb_sql_query_delete_t delete;
162
sb_sql_query_insert_t insert;
163
sb_sql_query_call_t call;
164
/* Buffer for the 'c' table field in update_non_index and insert queries */
167
/* Buffer for the 'pad' table field in insert query */
169
unsigned long pad_len;
172
/* OLTP test commands */
173
static int oltp_cmd_help(void);
174
static int oltp_cmd_prepare(void);
175
static int oltp_cmd_cleanup(void);
177
/* OLTP test operations */
178
static int oltp_init(void);
179
static void oltp_print_mode(void);
180
static sb_request_t oltp_get_request(int);
181
static int oltp_execute_request(sb_request_t *, int);
182
static void oltp_print_stats(void);
183
static db_conn_t *oltp_connect(void);
184
static int oltp_disconnect(db_conn_t *);
185
static int oltp_done(void);
187
static sb_test_t oltp_test =
190
.lname = "OLTP test",
197
.print_mode = oltp_print_mode,
198
.get_request = oltp_get_request,
199
.execute_request = oltp_execute_request,
200
.print_stats = oltp_print_stats,
204
.help = oltp_cmd_help,
205
.prepare = oltp_cmd_prepare,
207
.cleanup = oltp_cmd_cleanup
213
/* Global variables */
214
static oltp_args_t args; /* test args */
215
static unsigned int (*rnd_func)(void); /* pointer to random numbers generator */
216
static unsigned int req_performed; /* number of requests done */
217
static db_conn_t **connections; /* database connection pool */
218
static oltp_stmt_set_t *statements; /* prepared statements pool */
219
static oltp_bind_set_t *bind_bufs; /* bind buffers pool */
220
static db_driver_t *driver; /* current database driver */
221
static drv_caps_t driver_caps; /* driver capabilities */
223
/* Statistic counters */
225
static int write_ops;
226
static int other_ops;
227
static int transactions;
228
static int deadlocks;
230
static sb_timer_t *exec_timers;
231
static sb_timer_t *fetch_timers;
233
/* Random seed used to generate unique random numbers */
234
static unsigned long long rnd_seed;
235
/* Mutex to protect random seed */
236
static pthread_mutex_t rnd_mutex;
238
/* Variable to pass is_null flag to drivers */
240
static char oltp_is_null = 1;
242
/* Parse command line arguments */
243
static int parse_arguments(void);
245
/* Random number generators */
246
static unsigned int rnd_func_uniform(void);
247
static unsigned int rnd_func_gaussian(void);
248
static unsigned int rnd_func_special(void);
249
static unsigned int get_unique_random_id(void);
251
/* SQL request generators */
252
static sb_request_t get_request_simple(void);
253
static sb_request_t get_request_complex(void);
254
static sb_request_t get_request_nontrx(void);
255
static sb_request_t get_request_sp(void);
257
/* Get random 'user think' time */
258
static int get_think_time(void);
260
/* Generate SQL statement from query */
261
static db_stmt_t *get_sql_statement(sb_sql_query_t *, int);
262
static db_stmt_t *get_sql_statement_trx(sb_sql_query_t *, int);
263
static db_stmt_t *get_sql_statement_nontrx(sb_sql_query_t *, int);
264
static db_stmt_t *get_sql_statement_sp(sb_sql_query_t *, int);
266
/* Prepare a set of statements for test */
267
static int prepare_stmt_set(oltp_stmt_set_t *, oltp_bind_set_t *, db_conn_t *);
268
static int prepare_stmt_set_trx(oltp_stmt_set_t *, oltp_bind_set_t *, db_conn_t *);
269
static int prepare_stmt_set_nontrx(oltp_stmt_set_t *, oltp_bind_set_t *, db_conn_t *);
270
static int prepare_stmt_set_sp(oltp_stmt_set_t *, oltp_bind_set_t *, db_conn_t *);
272
/* Close a set of statements */
273
void close_stmt_set(oltp_stmt_set_t *set);
275
int register_test_oltp(sb_list_t *tests)
277
/* Register database API */
281
/* Register OLTP test */
282
SB_LIST_ADD_TAIL(&oltp_test.listitem, tests);
288
int oltp_cmd_help(void)
296
int oltp_cmd_prepare(void)
300
unsigned int query_len;
305
unsigned long commit_cntr = 0;
306
char insert_str[MAX_QUERY_LEN];
308
char *table_options_str;
310
if (parse_arguments())
313
/* Get database capabilites */
314
if (db_describe(driver, &driver_caps, NULL))
316
log_text(LOG_FATAL, "failed to get database capabilities!");
320
/* Create database connection */
321
con = oltp_connect();
325
/* Determine if database supports multiple row inserts */
326
if (driver_caps.multi_rows_insert)
331
/* Prepare statement buffer */
333
snprintf(insert_str, sizeof(insert_str),
334
"(0,' ','qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt')");
336
snprintf(insert_str, sizeof(insert_str),
337
"(%d,0,' ','qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt')",
340
query_len = MAX_QUERY_LEN + nrows * (strlen(insert_str) + 1);
341
query = (char *)malloc(query_len);
344
log_text(LOG_FATAL, "memory allocation failure!");
348
/* Create test table */
349
log_text(LOG_NOTICE, "Creating table '%s'...", args.table_name);
350
table_options_str = driver_caps.table_options_str;
351
snprintf(query, query_len,
353
"id %s %s NOT NULL %s, "
354
"k integer %s DEFAULT '0' NOT NULL, "
355
"c char(120) DEFAULT '' NOT NULL, "
356
"pad char(60) DEFAULT '' NOT NULL, "
360
(args.auto_inc && driver_caps.serial) ? "SERIAL" : "INTEGER",
361
driver_caps.unsigned_int ? "UNSIGNED" : "",
362
(args.auto_inc && driver_caps.auto_increment) ? "AUTO_INCREMENT" : "",
363
driver_caps.unsigned_int ? "UNSIGNED" : "",
364
(table_options_str != NULL) ? table_options_str : ""
366
if (db_query(con, query) == NULL)
368
log_text(LOG_FATAL, "failed to create test table");
372
if (args.auto_inc && !driver_caps.serial && !driver_caps.auto_increment)
374
if (db_query(con, "CREATE SEQUENCE sbtest_seq") == NULL ||
376
"CREATE TRIGGER sbtest_trig BEFORE INSERT ON sbtest "
378
"BEGIN SELECT sbtest_seq.nextval INTO :new.id FROM DUAL; "
382
log_text(LOG_FATAL, "failed to create test table");
387
/* Create secondary index on 'k' */
388
snprintf(query, query_len,
389
"CREATE INDEX k on %s(k)",
391
if (db_query(con, query) == NULL)
393
log_text(LOG_FATAL, "failed to create secondary index on table!");
396
/* Fill test table with data */
397
log_text(LOG_NOTICE, "Creating %d records in table '%s'...", args.table_size,
400
for (i = 0; i < args.table_size; i += nrows)
404
n = snprintf(query, query_len, "INSERT INTO %s(k, c, pad) VALUES ",
407
n = snprintf(query, query_len, "INSERT INTO %s(id, k, c, pad) VALUES ",
411
log_text(LOG_FATAL, "query is too long!");
415
for (j = 0; j < nrows; j++)
417
if ((unsigned)(pos - query) >= query_len)
419
log_text(LOG_FATAL, "query is too long!");
423
/* Form the values string when if are not using auto_inc */
425
snprintf(insert_str, sizeof(insert_str),
426
"(%d,0,' ','qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt')",
429
if (j == nrows - 1 || i+j == args.table_size -1)
430
n = snprintf(pos, query_len - (pos - query), "%s", insert_str);
432
n = snprintf(pos, query_len - (pos - query), "%s,", insert_str);
433
if (n >= query_len - (pos - query))
435
log_text(LOG_FATAL, "query is too long!");
438
if (i+j == args.table_size - 1)
444
if (db_query(con, query) == NULL)
446
log_text(LOG_FATAL, "failed to create test table!");
450
if (driver_caps.needs_commit)
452
commit_cntr += nrows;
453
if (commit_cntr >= ROWS_BEFORE_COMMIT)
455
if (db_query(con, "COMMIT") == NULL)
457
log_text(LOG_FATAL, "failed to commit inserted rows!");
460
commit_cntr -= ROWS_BEFORE_COMMIT;
465
if (driver_caps.needs_commit && db_query(con, "COMMIT") == NULL)
467
if (db_query(con, "COMMIT") == NULL)
469
log_text(LOG_FATAL, "failed to commit inserted rows!");
474
oltp_disconnect(con);
479
oltp_disconnect(con);
486
int oltp_cmd_cleanup(void)
491
if (parse_arguments())
494
/* Get database capabilites */
495
if (db_describe(driver, &driver_caps, NULL))
497
log_text(LOG_FATAL, "failed to get database capabilities!");
501
/* Create database connection */
502
con = oltp_connect();
506
/* Drop the test table */
507
log_text(LOG_NOTICE, "Dropping table '%s'...", args.table_name);
508
snprintf(query, sizeof(query), "DROP TABLE %s", args.table_name);
509
if (db_query(con, query) == NULL)
511
oltp_disconnect(con);
515
oltp_disconnect(con);
516
log_text(LOG_INFO, "Done.");
524
unsigned int thread_id;
525
char query[MAX_QUERY_LEN];
527
if (parse_arguments())
530
/* Get database capabilites */
531
if (db_describe(driver, &driver_caps, args.table_name))
533
log_text(LOG_FATAL, "failed to get database capabilities!");
537
/* Truncate table in case of nontrx INSERT test */
538
if (args.test_mode == TEST_MODE_NONTRX && args.nontrx_mode == NONTRX_MODE_INSERT)
540
con = oltp_connect();
543
snprintf(query, sizeof(query), "TRUNCATE TABLE %s", args.table_name);
544
if (db_query(con, query) == NULL)
546
oltp_disconnect(con);
549
/* Allocate database connection pool */
550
connections = (db_conn_t **)malloc(sb_globals.num_threads * sizeof(db_conn_t *));
551
if (connections == NULL)
553
log_text(LOG_FATAL, "failed to allocate DB connection pool!");
557
/* Create database connections */
558
for (thread_id = 0; thread_id < sb_globals.num_threads; thread_id++)
560
connections[thread_id] = oltp_connect();
561
if (connections[thread_id] == NULL)
563
log_text(LOG_FATAL, "thread#%d: failed to connect to database server, aborting...",
569
/* Allocate statements pool */
570
statements = (oltp_stmt_set_t *)calloc(sb_globals.num_threads,
571
sizeof(oltp_stmt_set_t));
572
if (statements == NULL)
574
log_text(LOG_FATAL, "failed to allocate statements pool!");
578
/* Allocate bind buffers for each thread */
579
bind_bufs = (oltp_bind_set_t *)calloc(sb_globals.num_threads,
580
sizeof(oltp_bind_set_t));
581
/* Prepare statements for each thread */
582
for (thread_id = 0; thread_id < sb_globals.num_threads; thread_id++)
584
if (prepare_stmt_set(statements + thread_id, bind_bufs + thread_id,
585
connections[thread_id]))
587
log_text(LOG_FATAL, "thread#%d: failed to prepare statements for test",
593
/* Initialize random seed for non-transactional delete test */
594
if (args.test_mode == TEST_MODE_NONTRX)
596
rnd_seed = LARGE_PRIME;
597
pthread_mutex_init(&rnd_mutex, NULL);
600
/* Initialize internal timers if we are in the debug mode */
601
if (sb_globals.debug)
603
exec_timers = (sb_timer_t *)malloc(sb_globals.num_threads * sizeof(sb_timer_t));
604
fetch_timers = (sb_timer_t *)malloc(sb_globals.num_threads * sizeof(sb_timer_t));
605
for (thread_id = 0; thread_id < sb_globals.num_threads; thread_id++)
607
sb_timer_init(exec_timers + thread_id);
608
sb_timer_init(fetch_timers + thread_id);
618
unsigned int thread_id;
620
if (args.test_mode == TEST_MODE_NONTRX)
621
pthread_mutex_destroy(&rnd_mutex);
623
/* Close statements and database connections */
624
for (thread_id = 0; thread_id < sb_globals.num_threads; thread_id++)
626
close_stmt_set(statements + thread_id);
627
oltp_disconnect(connections[thread_id]);
630
/* Deallocate connection pool */
640
void oltp_print_mode(void)
642
log_text(LOG_NOTICE, "Doing OLTP test.");
644
switch (args.test_mode) {
645
case TEST_MODE_SIMPLE:
646
log_text(LOG_NOTICE, "Running simple OLTP test");
648
case TEST_MODE_COMPLEX:
649
log_text(LOG_NOTICE, "Running mixed OLTP test");
651
case TEST_MODE_NONTRX:
652
log_text(LOG_NOTICE, "Running non-transactional test");
655
log_text(LOG_NOTICE, "Running stored procedure test");
659
log_text(LOG_WARNING, "Unknown OLTP test mode!");
664
log_text(LOG_NOTICE, "Doing read-only test");
666
switch (args.dist_type) {
667
case DIST_TYPE_UNIFORM:
668
log_text(LOG_NOTICE, "Using Uniform distribution");
670
case DIST_TYPE_GAUSSIAN:
671
log_text(LOG_NOTICE, "Using Normal distribution (%d iterations)",
674
case DIST_TYPE_SPECIAL:
675
log_text(LOG_NOTICE, "Using Special distribution (%d iterations, "
676
"%d pct of values are returned in %d pct cases)",
677
args.dist_iter, args.dist_pct, args.dist_res);
680
log_text(LOG_WARNING, "Unknown distribution!");
685
log_text(LOG_NOTICE, "Skipping BEGIN/COMMIT");
687
log_text(LOG_NOTICE, "Using \"%s%s\" for starting transactions",
688
driver_caps.transactions ? "BEGIN" : "LOCK TABLES",
689
(driver_caps.transactions) ? "" :
690
((args.read_only) ? " READ" : " WRITE"));
693
log_text(LOG_NOTICE, "Using auto_inc on the id column");
695
log_text(LOG_NOTICE, "Not using auto_inc on the id column");
697
if (sb_globals.max_requests > 0)
699
"Maximum number of requests for OLTP test is limited to %d",
700
sb_globals.max_requests);
701
if (sb_globals.validate)
702
log_text(LOG_NOTICE, "Validation mode enabled");
706
sb_request_t oltp_get_request(int tid)
710
(void)tid; /* unused */
712
if (sb_globals.max_requests > 0 && req_performed >= sb_globals.max_requests)
714
sb_req.type = SB_REQ_TYPE_NULL;
718
switch (args.test_mode) {
719
case TEST_MODE_SIMPLE:
720
return get_request_simple();
721
case TEST_MODE_COMPLEX:
722
return get_request_complex();
723
case TEST_MODE_NONTRX:
724
return get_request_nontrx();
726
return get_request_sp();
728
log_text(LOG_FATAL, "unknown test mode: %d!", args.test_mode);
729
sb_req.type = SB_REQ_TYPE_NULL;
736
sb_request_t get_request_sp(void)
739
sb_sql_request_t *sql_req = &sb_req.u.sql_request;
740
sb_sql_query_t *query;
742
sb_req.type = SB_REQ_TYPE_SQL;
744
sql_req->queries = (sb_list_t *)malloc(sizeof(sb_list_t));
745
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
746
if (sql_req->queries == NULL || query == NULL)
748
log_text(LOG_FATAL, "cannot allocate SQL query!");
749
sb_req.type = SB_REQ_TYPE_NULL;
753
SB_LIST_INIT(sql_req->queries);
754
query->num_times = 1;
755
query->think_time = get_think_time();
756
query->type = SB_SQL_QUERY_CALL;
758
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
766
sb_request_t get_request_simple(void)
769
sb_sql_request_t *sql_req = &sb_req.u.sql_request;
770
sb_sql_query_t *query;
772
sb_req.type = SB_REQ_TYPE_SQL;
774
sql_req->queries = (sb_list_t *)malloc(sizeof(sb_list_t));
775
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
776
if (sql_req->queries == NULL || query == NULL)
778
log_text(LOG_FATAL, "cannot allocate SQL query!");
779
sb_req.type = SB_REQ_TYPE_NULL;
783
SB_LIST_INIT(sql_req->queries);
784
query->num_times = 1;
785
query->think_time = get_think_time();
786
query->type = SB_SQL_QUERY_POINT;
787
query->u.point_query.id = GET_RANDOM_ID();
789
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
797
sb_request_t get_request_complex(void)
800
sb_sql_request_t *sql_req = &sb_req.u.sql_request;
801
sb_sql_query_t *query;
807
sb_req.type = SB_REQ_TYPE_SQL;
809
sql_req->queries = (sb_list_t *)malloc(sizeof(sb_list_t));
810
if (sql_req->queries == NULL)
812
log_text(LOG_FATAL, "cannot allocate SQL query!");
813
sb_req.type = SB_REQ_TYPE_NULL;
816
SB_LIST_INIT(sql_req->queries);
820
/* Generate BEGIN statement */
821
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
824
query->type = SB_SQL_QUERY_LOCK;
825
query->num_times = 1;
826
query->think_time = 0;
827
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
830
/* Generate set of point selects */
831
for(i = 0; i < args.point_selects; i++)
833
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
836
query->num_times = 1;
837
query->think_time = get_think_time();
838
query->type = SB_SQL_QUERY_POINT;
839
query->u.point_query.id = GET_RANDOM_ID();
841
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
844
/* Generate range queries */
845
for(i = 0; i < args.simple_ranges; i++)
847
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
850
query->num_times = 1;
851
query->think_time = get_think_time();
852
query->type = SB_SQL_QUERY_RANGE;
853
range = GET_RANDOM_ID();
854
if (range + args.range_size > args.table_size)
855
range = args.table_size - args.range_size;
858
query->u.range_query.from = range;
859
query->u.range_query.to = range + args.range_size - 1;
860
query->nrows = args.range_size;
861
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
864
/* Generate sum range queries */
865
for(i = 0; i < args.sum_ranges; i++)
867
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
870
query->num_times = 1;
871
query->think_time = get_think_time();
872
query->type = SB_SQL_QUERY_RANGE_SUM;
873
range = GET_RANDOM_ID();
874
if (range + args.range_size > args.table_size)
875
range = args.table_size - args.range_size;
878
query->u.range_query.from = range;
879
query->u.range_query.to = range + args.range_size - 1;
881
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
884
/* Generate ordered range queries */
885
for(i = 0; i < args.order_ranges; i++)
887
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
890
query->num_times = 1;
891
query->think_time = get_think_time();
892
query->type = SB_SQL_QUERY_RANGE_ORDER;
893
range = GET_RANDOM_ID();
894
if (range + args.range_size > args.table_size)
895
range = args.table_size - args.range_size;
898
query->u.range_query.from = range;
899
query->u.range_query.to = range + args.range_size - 1;
900
query->nrows = args.range_size;
901
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
904
/* Generate distinct range queries */
905
for(i = 0; i < args.distinct_ranges; i++)
907
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
910
query->num_times = 1;
911
query->think_time = get_think_time();
912
query->type = SB_SQL_QUERY_RANGE_DISTINCT;
913
range = GET_RANDOM_ID();
914
if (range + args.range_size > args.table_size)
915
range = args.table_size - args.range_size;
918
query->u.range_query.from = range;
919
query->u.range_query.to = range + args.range_size;
921
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
924
/* Skip all write queries for read-only test mode */
928
/* Generate index update */
929
for (i = 0; i < args.index_updates; i++)
931
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
934
query->num_times = 1;
935
query->think_time = get_think_time();
936
query->type = SB_SQL_QUERY_UPDATE_INDEX;
937
query->u.update_query.id = GET_RANDOM_ID();
938
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
941
/* Generate non-index update */
942
for (i = 0; i < args.non_index_updates; i++)
944
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
947
query->num_times = 1;
948
query->think_time = get_think_time();
949
query->type = SB_SQL_QUERY_UPDATE_NON_INDEX;
950
query->u.update_query.id = GET_RANDOM_ID();
951
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
954
/* FIXME: generate one more UPDATE with the same ID as DELETE/INSERT to make
956
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
959
query->num_times = 1;
960
query->think_time = get_think_time();
961
query->type = SB_SQL_QUERY_UPDATE_INDEX;
962
range = GET_RANDOM_ID();
963
query->u.update_query.id = range;
964
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
966
/* Generate delete */
967
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
970
query->num_times = 1;
971
query->think_time = get_think_time();
972
query->type = SB_SQL_QUERY_DELETE;
973
/* FIXME range = GET_RANDOM_ID(); */
974
query->u.delete_query.id = range;
975
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
977
/* Generate insert with same value */
978
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
981
query->num_times = 1;
982
query->think_time = get_think_time();
983
query->type = SB_SQL_QUERY_INSERT;
984
query->u.insert_query.id = range;
985
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
991
/* Generate commit */
992
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
995
query->type = SB_SQL_QUERY_UNLOCK;
996
query->num_times = 1;
997
query->think_time = 0;
998
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
1001
/* return request */
1005
/* Handle memory allocation failures */
1007
log_text(LOG_FATAL, "cannot allocate SQL query!");
1008
SB_LIST_FOR_EACH_SAFE(pos, tmp, sql_req->queries)
1010
query = SB_LIST_ENTRY(pos, sb_sql_query_t, listitem);
1013
free(sql_req->queries);
1014
sb_req.type = SB_REQ_TYPE_NULL;
1019
sb_request_t get_request_nontrx(void)
1021
sb_request_t sb_req;
1022
sb_sql_request_t *sql_req = &sb_req.u.sql_request;
1023
sb_sql_query_t *query;
1025
sb_req.type = SB_REQ_TYPE_SQL;
1027
sql_req->queries = (sb_list_t *)malloc(sizeof(sb_list_t));
1028
if (sql_req->queries == NULL)
1030
log_text(LOG_FATAL, "cannot allocate SQL query!");
1031
sb_req.type = SB_REQ_TYPE_NULL;
1034
SB_LIST_INIT(sql_req->queries);
1036
query = (sb_sql_query_t *)malloc(sizeof(sb_sql_query_t));
1039
query->num_times = 1;
1040
query->think_time = get_think_time();
1042
switch (args.nontrx_mode) {
1043
case NONTRX_MODE_SELECT:
1044
query->type = SB_SQL_QUERY_POINT;
1045
query->u.point_query.id = GET_RANDOM_ID();
1048
case NONTRX_MODE_UPDATE_KEY:
1049
query->type = SB_SQL_QUERY_UPDATE_INDEX;
1050
query->u.update_query.id = GET_RANDOM_ID();
1052
case NONTRX_MODE_UPDATE_NOKEY:
1053
query->type = SB_SQL_QUERY_UPDATE_NON_INDEX;
1054
query->u.update_query.id = GET_RANDOM_ID();
1056
case NONTRX_MODE_INSERT:
1057
query->type = SB_SQL_QUERY_INSERT;
1058
query->u.update_query.id = GET_RANDOM_ID();
1060
case NONTRX_MODE_DELETE:
1061
query->type = SB_SQL_QUERY_DELETE;
1062
query->u.delete_query.id = get_unique_random_id();
1065
log_text(LOG_FATAL, "unknown mode for non-transactional test!");
1067
sb_req.type = SB_REQ_TYPE_NULL;
1071
SB_LIST_ADD_TAIL(&query->listitem, sql_req->queries);
1073
/* return request */
1077
/* Handle memory allocation failures */
1079
log_text(LOG_FATAL, "cannot allocate SQL query!");
1082
free(sql_req->queries);
1083
sb_req.type = SB_REQ_TYPE_NULL;
1089
* We measure read operations, write operations and transactions
1090
* performance. The time is counted for atomic operations as user might sleep
1091
* before some of them.
1095
int oltp_execute_request(sb_request_t *sb_req, int thread_id)
1098
sb_sql_request_t *sql_req = &sb_req->u.sql_request;
1100
db_result_set_t *rs;
1101
sb_list_item_t *pos;
1102
sb_list_item_t *tmp;
1103
sb_sql_query_t *query;
1105
unsigned int local_read_ops=0;
1106
unsigned int local_write_ops=0;
1107
unsigned int local_other_ops=0;
1108
unsigned int local_deadlocks=0;
1111
log_msg_oper_t op_msg;
1112
unsigned long long nrows;
1114
/* Prepare log message */
1115
msg.type = LOG_MSG_TYPE_OPER;
1118
/* measure the time for transaction */
1119
LOG_EVENT_START(msg, thread_id);
1121
do /* deadlock handling */
1124
SB_LIST_FOR_EACH(pos, sql_req->queries)
1126
query = SB_LIST_ENTRY(pos, sb_sql_query_t, listitem);
1128
for(i = 0; i < query->num_times; i++)
1130
/* emulate user thinking */
1131
if (query->think_time > 0)
1132
usleep(query->think_time);
1134
/* find prepared statement */
1135
stmt = get_sql_statement(query, thread_id);
1138
log_text(LOG_FATAL, "unknown SQL query type: %d!", query->type);
1139
sb_globals.error = 1;
1143
if (sb_globals.debug)
1144
sb_timer_start(exec_timers + thread_id);
1146
rs = db_execute(stmt);
1148
if (sb_globals.debug)
1149
sb_timer_stop(exec_timers + thread_id);
1153
rc = db_errno(connections[thread_id]);
1154
if (rc != SB_DB_ERROR_DEADLOCK)
1156
log_text(LOG_FATAL, "database error, exiting...");
1157
/* exiting, forget about allocated memory */
1158
sb_globals.error = 1;
1170
if (query->type >= SB_SQL_QUERY_POINT &&
1171
query->type <= SB_SQL_QUERY_RANGE_DISTINCT) /* select query */
1173
if (sb_globals.debug)
1174
sb_timer_start(fetch_timers + thread_id);
1176
rc = db_store_results(rs);
1178
if (sb_globals.debug)
1179
sb_timer_stop(fetch_timers + thread_id);
1182
if (rc == SB_DB_ERROR_DEADLOCK)
1184
db_free_results(rs);
1189
else if (rc != SB_DB_ERROR_NONE)
1191
log_text(LOG_FATAL, "Error fetching result: `%s`", stmt);
1192
/* exiting, forget about allocated memory */
1193
sb_globals.error = 1;
1197
/* Validate the result set if requested */
1198
if (sb_globals.validate && query->nrows > 0)
1200
nrows = db_num_rows(rs);
1201
if (nrows != query->nrows)
1202
log_text(LOG_WARNING,
1203
"Number of received rows mismatch, expected: %ld, actual: %ld",
1204
(long )query->nrows, (long)nrows);
1208
db_free_results(rs);
1211
/* count operation statistics */
1212
switch(query->type) {
1213
case SB_SQL_QUERY_POINT:
1214
case SB_SQL_QUERY_RANGE:
1215
case SB_SQL_QUERY_RANGE_SUM:
1216
case SB_SQL_QUERY_RANGE_ORDER:
1217
case SB_SQL_QUERY_RANGE_DISTINCT:
1218
local_read_ops += query->num_times;
1220
case SB_SQL_QUERY_UPDATE_INDEX:
1221
case SB_SQL_QUERY_UPDATE_NON_INDEX:
1222
case SB_SQL_QUERY_DELETE:
1223
case SB_SQL_QUERY_INSERT:
1224
local_write_ops += query->num_times;
1227
local_other_ops += query->num_times;
1230
break; /* break transaction execution if deadlock */
1232
} while(retry); /* retry transaction in case of deadlock */
1234
LOG_EVENT_STOP(msg, thread_id);
1236
SB_THREAD_MUTEX_LOCK();
1237
read_ops += local_read_ops;
1238
write_ops += local_write_ops;
1239
other_ops += local_other_ops;
1241
deadlocks += local_deadlocks;
1242
SB_THREAD_MUTEX_UNLOCK();
1244
/* Free list of queries */
1245
SB_LIST_FOR_EACH_SAFE(pos, tmp, sql_req->queries)
1247
query = SB_LIST_ENTRY(pos, sb_sql_query_t, listitem);
1250
free(sql_req->queries);
1256
void oltp_print_stats(void)
1260
sb_timer_t exec_timer;
1261
sb_timer_t fetch_timer;
1263
total_time = NS2SEC(sb_timer_value(&sb_globals.exec_timer));
1265
log_text(LOG_NOTICE, "OLTP test statistics:");
1266
log_text(LOG_NOTICE, " queries performed:");
1267
log_text(LOG_NOTICE, " read: %d",
1269
log_text(LOG_NOTICE, " write: %d",
1271
log_text(LOG_NOTICE, " other: %d",
1273
log_text(LOG_NOTICE, " total: %d",
1274
read_ops + write_ops + other_ops);
1275
log_text(LOG_NOTICE, " transactions: %-6d"
1276
" (%.2f per sec.)", transactions, transactions / total_time);
1277
log_text(LOG_NOTICE, " deadlocks: %-6d"
1278
" (%.2f per sec.)", deadlocks, deadlocks / total_time);
1279
log_text(LOG_NOTICE, " read/write requests: %-6d"
1280
" (%.2f per sec.)", read_ops + write_ops,
1281
(read_ops + write_ops) / total_time);
1282
log_text(LOG_NOTICE, " other operations: %-6d"
1283
" (%.2f per sec.)", other_ops, other_ops / total_time);
1285
if (sb_globals.debug)
1287
sb_timer_init(&exec_timer);
1288
sb_timer_init(&fetch_timer);
1290
for (i = 0; i < sb_globals.num_threads; i++)
1292
exec_timer = merge_timers(&exec_timer, exec_timers + i);
1293
fetch_timer = merge_timers(&fetch_timer, fetch_timers + i);
1296
log_text(LOG_DEBUG, "");
1297
log_text(LOG_DEBUG, "Query execution statistics:");
1298
log_text(LOG_DEBUG, " min: %.4fs",
1299
NS2SEC(get_min_time(&exec_timer)));
1300
log_text(LOG_DEBUG, " avg: %.4fs",
1301
NS2SEC(get_avg_time(&exec_timer)));
1302
log_text(LOG_DEBUG, " max: %.4fs",
1303
NS2SEC(get_max_time(&exec_timer)));
1304
log_text(LOG_DEBUG, " total: %.4fs",
1305
NS2SEC(get_sum_time(&exec_timer)));
1307
log_text(LOG_DEBUG, "Results fetching statistics:");
1308
log_text(LOG_DEBUG, " min: %.4fs",
1309
NS2SEC(get_min_time(&fetch_timer)));
1310
log_text(LOG_DEBUG, " avg: %.4fs",
1311
NS2SEC(get_avg_time(&fetch_timer)));
1312
log_text(LOG_DEBUG, " max: %.4fs",
1313
NS2SEC(get_max_time(&fetch_timer)));
1314
log_text(LOG_DEBUG, " total: %.4fs",
1315
NS2SEC(get_sum_time(&fetch_timer)));
1320
db_conn_t *oltp_connect(void)
1324
con = db_connect(driver);
1327
log_text(LOG_FATAL, "failed to connect to database server!");
1331
if (args.connect_delay > 0)
1332
usleep(args.connect_delay);
1338
int oltp_disconnect(db_conn_t *con)
1340
return db_disconnect(con);
1344
/* Parse command line arguments */
1347
int parse_arguments(void)
1351
s = sb_get_value_string("oltp-test-mode");
1352
if (!strcmp(s, "simple"))
1353
args.test_mode = TEST_MODE_SIMPLE;
1354
else if (!strcmp(s, "complex"))
1355
args.test_mode = TEST_MODE_COMPLEX;
1356
else if (!strcmp(s, "nontrx"))
1357
args.test_mode = TEST_MODE_NONTRX;
1358
else if (!strcmp(s, "sp"))
1359
args.test_mode = TEST_MODE_SP;
1362
log_text(LOG_FATAL, "Invalid OLTP test mode: %s.", s);
1366
args.sp_name = sb_get_value_string("oltp-sp-name");
1367
if (args.test_mode == TEST_MODE_SP && args.sp_name == NULL)
1369
log_text(LOG_FATAL, "Name of stored procedure must be specified with --oltp-sp-name "
1374
args.read_only = sb_get_value_flag("oltp-read-only");
1375
args.skip_trx = sb_get_value_flag("oltp-skip-trx");
1376
args.auto_inc = sb_get_value_flag("oltp-auto-inc");
1377
args.range_size = sb_get_value_int("oltp-range-size");
1378
args.point_selects = sb_get_value_int("oltp-point-selects");
1379
args.simple_ranges = sb_get_value_int("oltp-simple-ranges");
1380
args.sum_ranges = sb_get_value_int("oltp-sum-ranges");
1381
args.order_ranges = sb_get_value_int("oltp-order-ranges");
1382
args.distinct_ranges = sb_get_value_int("oltp-distinct-ranges");
1383
args.index_updates = sb_get_value_int("oltp-index-updates");
1384
args.non_index_updates = sb_get_value_int("oltp-non-index-updates");
1386
s = sb_get_value_string("oltp-nontrx-mode");
1387
if (!strcmp(s, "select"))
1388
args.nontrx_mode = NONTRX_MODE_SELECT;
1389
else if (!strcmp(s, "update_key"))
1390
args.nontrx_mode = NONTRX_MODE_UPDATE_KEY;
1391
else if (!strcmp(s, "update_nokey"))
1392
args.nontrx_mode = NONTRX_MODE_UPDATE_NOKEY;
1393
else if (!strcmp(s, "insert"))
1394
args.nontrx_mode = NONTRX_MODE_INSERT;
1395
else if (!strcmp(s, "delete"))
1396
args.nontrx_mode = NONTRX_MODE_DELETE;
1399
log_text(LOG_FATAL, "Invalid value of oltp-nontrx-mode: %s", s);
1403
args.connect_delay = sb_get_value_int("oltp-connect-delay");
1404
args.user_delay_min = sb_get_value_int("oltp-user-delay-min");
1405
args.user_delay_max = sb_get_value_int("oltp-user-delay-max");
1406
args.table_name = sb_get_value_string("oltp-table-name");
1407
args.table_size = sb_get_value_int("oltp-table-size");
1409
s = sb_get_value_string("oltp-dist-type");
1410
if (!strcmp(s, "uniform"))
1412
args.dist_type = DIST_TYPE_UNIFORM;
1413
rnd_func = &rnd_func_uniform;
1415
else if (!strcmp(s, "gaussian"))
1417
args.dist_type = DIST_TYPE_GAUSSIAN;
1418
rnd_func = &rnd_func_gaussian;
1420
else if (!strcmp(s, "special"))
1422
args.dist_type = DIST_TYPE_SPECIAL;
1423
rnd_func = &rnd_func_special;
1427
log_text(LOG_FATAL, "Invalid random numbers distribution: %s.", s);
1431
args.dist_iter = sb_get_value_int("oltp-dist-iter");
1432
args.dist_pct = sb_get_value_int("oltp-dist-pct");
1433
args.dist_res = sb_get_value_int("oltp-dist-res");
1435
/* Select driver according to command line arguments */
1436
driver = db_init(NULL);
1439
log_text(LOG_FATAL, "failed to initialize database driver!");
1447
/* Prepare a set of statements for the test */
1450
int prepare_stmt_set(oltp_stmt_set_t *set, oltp_bind_set_t *bufs, db_conn_t *conn)
1452
if (args.test_mode == TEST_MODE_NONTRX)
1453
return prepare_stmt_set_nontrx(set, bufs, conn);
1454
else if (args.test_mode == TEST_MODE_COMPLEX ||
1455
args.test_mode == TEST_MODE_SIMPLE)
1456
return prepare_stmt_set_trx(set, bufs, conn);
1458
return prepare_stmt_set_sp(set, bufs, conn);
1462
/* Close a set of statements for the test */
1464
void close_stmt_set(oltp_stmt_set_t *set)
1466
db_close(set->lock);
1467
db_close(set->unlock);
1468
db_close(set->point);
1469
db_close(set->call);
1470
db_close(set->range);
1471
db_close(set->range_sum);
1472
db_close(set->range_order);
1473
db_close(set->range_distinct);
1474
db_close(set->update_index);
1475
db_close(set->update_non_index);
1476
db_close(set->delete);
1477
db_close(set->insert);
1481
/* Generate SQL statement from query */
1484
db_stmt_t *get_sql_statement(sb_sql_query_t *query, int thread_id)
1486
if (args.test_mode == TEST_MODE_NONTRX)
1487
return get_sql_statement_nontrx(query, thread_id);
1488
else if (args.test_mode == TEST_MODE_COMPLEX ||
1489
args.test_mode == TEST_MODE_SIMPLE)
1490
return get_sql_statement_trx(query, thread_id);
1492
return get_sql_statement_sp(query, thread_id);
1496
/* Prepare a set of statements for SP test */
1499
int prepare_stmt_set_sp(oltp_stmt_set_t *set, oltp_bind_set_t *bufs, db_conn_t *conn)
1501
db_bind_t params[2];
1502
char query[MAX_QUERY_LEN];
1504
/* Prepare CALL statement */
1505
snprintf(query, MAX_QUERY_LEN, "CALL %s(?,?)", args.sp_name);
1506
set->call = db_prepare(conn, query);
1507
if (set->call == NULL)
1509
params[0].type = DB_TYPE_INT;
1510
params[0].buffer = &bufs->call.thread_id;
1511
params[0].is_null = 0;
1512
params[0].data_len = 0;
1513
params[1].type = DB_TYPE_INT;
1514
params[1].buffer = &bufs->call.nthreads;
1515
params[1].is_null = 0;
1516
params[1].data_len = 0;
1517
if (db_bind_param(set->call, params, 2))
1522
/* Prepare a set of statements for transactional test */
1525
int prepare_stmt_set_trx(oltp_stmt_set_t *set, oltp_bind_set_t *bufs, db_conn_t *conn)
1527
db_bind_t binds[11];
1528
char query[MAX_QUERY_LEN];
1530
/* Prepare the point statement */
1531
snprintf(query, MAX_QUERY_LEN, "SELECT c from %s where id=?",
1533
set->point = db_prepare(conn, query);
1534
if (set->point == NULL)
1536
binds[0].type = DB_TYPE_INT;
1537
binds[0].buffer = &bufs->point.id;
1538
binds[0].is_null = 0;
1539
binds[0].data_len = 0;
1540
if (db_bind_param(set->point, binds, 1))
1543
/* Prepare the range statement */
1544
snprintf(query, MAX_QUERY_LEN, "SELECT c from %s where id between ? and ?",
1546
set->range = db_prepare(conn, query);
1547
if (set->range == NULL)
1549
binds[0].type = DB_TYPE_INT;
1550
binds[0].buffer = &bufs->range.from;
1551
binds[0].is_null = 0;
1552
binds[0].data_len = 0;
1553
binds[1].type = DB_TYPE_INT;
1554
binds[1].buffer = &bufs->range.to;
1555
binds[1].is_null = 0;
1556
binds[1].data_len = 0;
1557
if (db_bind_param(set->range, binds, 2))
1560
/* Prepare the range_sum statement */
1561
snprintf(query, MAX_QUERY_LEN,
1562
"SELECT SUM(K) from %s where id between ? and ?", args.table_name);
1563
set->range_sum = db_prepare(conn, query);
1564
if (set->range_sum == NULL)
1566
binds[0].type = DB_TYPE_INT;
1567
binds[0].buffer = &bufs->range_sum.from;
1568
binds[0].is_null = 0;
1569
binds[0].data_len = 0;
1570
binds[1].type = DB_TYPE_INT;
1571
binds[1].buffer = &bufs->range_sum.to;
1572
binds[1].is_null = 0;
1573
binds[1].data_len = 0;
1574
if (db_bind_param(set->range_sum, binds, 2))
1577
/* Prepare the range_order statement */
1578
snprintf(query, MAX_QUERY_LEN,
1579
"SELECT c from %s where id between ? and ? order by c",
1581
set->range_order = db_prepare(conn, query);
1582
if (set->range_order == NULL)
1584
binds[0].type = DB_TYPE_INT;
1585
binds[0].buffer = &bufs->range_order.from;
1586
binds[0].is_null = 0;
1587
binds[0].data_len = 0;
1588
binds[1].type = DB_TYPE_INT;
1589
binds[1].buffer = &bufs->range_order.to;
1590
binds[1].is_null = 0;
1591
binds[1].data_len = 0;
1592
if (db_bind_param(set->range_order, binds, 2))
1595
/* Prepare the range_distinct statement */
1596
snprintf(query, MAX_QUERY_LEN,
1597
"SELECT DISTINCT c from %s where id between ? and ? order by c",
1599
set->range_distinct = db_prepare(conn, query);
1600
if (set->range_distinct == NULL)
1602
binds[0].type = DB_TYPE_INT;
1603
binds[0].buffer = &bufs->range_distinct.from;
1604
binds[0].is_null = 0;
1605
binds[0].data_len = 0;
1606
binds[1].type = DB_TYPE_INT;
1607
binds[1].buffer = &bufs->range_distinct.to;
1608
binds[1].is_null = 0;
1609
binds[1].data_len = 0;
1610
if (db_bind_param(set->range_distinct, binds, 2))
1613
/* Prepare the update_index statement */
1614
snprintf(query, MAX_QUERY_LEN, "UPDATE %s set k=k+1 where id=?",
1616
set->update_index = db_prepare(conn, query);
1617
if (set->update_index == NULL)
1619
binds[0].type = DB_TYPE_INT;
1620
binds[0].buffer = &bufs->update_index.id;
1621
binds[0].is_null = 0;
1622
binds[0].data_len = 0;
1623
if (db_bind_param(set->update_index, binds, 1))
1626
/* Prepare the update_non_index statement */
1627
snprintf(query, MAX_QUERY_LEN,
1628
"UPDATE %s set c=? where id=?",
1630
set->update_non_index = db_prepare(conn, query);
1631
if (set->update_non_index == NULL)
1634
Non-index update statement is re-bound each time because of the string
1638
/* Prepare the delete statement */
1639
snprintf(query, MAX_QUERY_LEN, "DELETE from %s where id=?",
1641
set->delete = db_prepare(conn, query);
1642
if (set->delete == NULL)
1644
binds[0].type = DB_TYPE_INT;
1645
binds[0].buffer = &bufs->delete.id;
1646
binds[0].is_null = 0;
1647
binds[0].data_len = 0;
1648
if (db_bind_param(set->delete, binds, 1))
1651
/* Prepare the insert statement */
1652
snprintf(query, MAX_QUERY_LEN, "INSERT INTO %s values(?,0,' ',"
1653
"'aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')",
1655
set->insert = db_prepare(conn, query);
1656
if (set->insert == NULL)
1658
binds[0].type = DB_TYPE_INT;
1659
binds[0].buffer = &bufs->insert.id;
1660
binds[0].is_null = 0;
1661
binds[0].data_len = 0;
1662
if (db_bind_param(set->insert, binds, 1))
1668
/* Prepare the lock statement */
1669
if (driver_caps.transactions)
1670
strncpy(query, "BEGIN", MAX_QUERY_LEN);
1674
snprintf(query, MAX_QUERY_LEN, "LOCK TABLES %s READ", args.table_name);
1676
snprintf(query, MAX_QUERY_LEN, "LOCK TABLES %s WRITE", args.table_name);
1678
set->lock = db_prepare(conn, query);
1679
if (set->lock == NULL)
1682
/* Prepare the unlock statement */
1683
if (driver_caps.transactions)
1684
strncpy(query, "COMMIT", MAX_QUERY_LEN);
1686
strncpy(query, "UNLOCK TABLES", MAX_QUERY_LEN);
1687
set->unlock = db_prepare(conn, query);
1688
if (set->unlock == NULL)
1695
/* Prepare a set of statements for non-transactional test */
1698
int prepare_stmt_set_nontrx(oltp_stmt_set_t *set, oltp_bind_set_t *bufs, db_conn_t *conn)
1700
db_bind_t binds[11];
1701
char query[MAX_QUERY_LEN];
1703
/* Prepare the point statement */
1704
snprintf(query, MAX_QUERY_LEN, "SELECT pad from %s where id=?",
1706
set->point = db_prepare(conn, query);
1707
if (set->point == NULL)
1709
binds[0].type = DB_TYPE_INT;
1710
binds[0].buffer = &bufs->point.id;
1711
binds[0].is_null = 0;
1712
binds[0].data_len = 0;
1713
if (db_bind_param(set->point, binds, 1))
1716
/* Prepare the update_index statement */
1717
snprintf(query, MAX_QUERY_LEN, "UPDATE %s set k=k+1 where id=?",
1719
set->update_index = db_prepare(conn, query);
1720
if (set->update_index == NULL)
1722
binds[0].type = DB_TYPE_INT;
1723
binds[0].buffer = &bufs->update_index.id;
1724
binds[0].is_null = 0;
1725
binds[0].data_len = 0;
1726
if (db_bind_param(set->update_index, binds, 1))
1729
/* Prepare the update_non_index statement */
1730
snprintf(query, MAX_QUERY_LEN,
1731
"UPDATE %s set c=? where id=?",
1733
set->update_non_index = db_prepare(conn, query);
1734
if (set->update_non_index == NULL)
1737
Non-index update statement is re-bound each time because of the string
1741
/* Prepare the delete statement */
1742
snprintf(query, MAX_QUERY_LEN, "DELETE from %s where id=?",
1744
set->delete = db_prepare(conn, query);
1745
if (set->delete == NULL)
1747
binds[0].type = DB_TYPE_INT;
1748
binds[0].buffer = &bufs->delete.id;
1749
binds[0].is_null = 0;
1750
binds[0].data_len = 0;
1751
if (db_bind_param(set->delete, binds, 1))
1754
/* Prepare the insert statement */
1755
snprintf(query, MAX_QUERY_LEN, "INSERT INTO %s values(?,?,?,?)",
1757
set->insert = db_prepare(conn, query);
1759
Insert statement is re-bound each time because of the string
1767
/* Generate SQL statement from query for SP test */
1770
db_stmt_t *get_sql_statement_sp(sb_sql_query_t *query, int thread_id)
1773
oltp_bind_set_t *buf = bind_bufs + thread_id;
1775
(void) query; /* unused */
1777
stmt = statements[thread_id].call;
1778
buf->call.thread_id = thread_id;
1779
buf->call.nthreads = sb_globals.num_threads;
1785
/* Generate SQL statement from query for transactional test */
1788
db_stmt_t *get_sql_statement_trx(sb_sql_query_t *query, int thread_id)
1790
db_stmt_t *stmt = NULL;
1792
oltp_bind_set_t *buf = bind_bufs + thread_id;
1794
switch (query->type) {
1795
case SB_SQL_QUERY_LOCK:
1796
stmt = statements[thread_id].lock;
1799
case SB_SQL_QUERY_UNLOCK:
1800
stmt = statements[thread_id].unlock;
1803
case SB_SQL_QUERY_POINT:
1804
stmt = statements[thread_id].point;
1805
buf->point.id = query->u.point_query.id;
1808
case SB_SQL_QUERY_RANGE:
1809
stmt = statements[thread_id].range;
1810
buf->range.from = query->u.range_query.from;
1811
buf->range.to = query->u.range_query.to;
1814
case SB_SQL_QUERY_RANGE_SUM:
1815
stmt = statements[thread_id].range_sum;
1816
buf->range_sum.from = query->u.range_query.from;
1817
buf->range_sum.to = query->u.range_query.to;
1820
case SB_SQL_QUERY_RANGE_ORDER:
1821
stmt = statements[thread_id].range_order;
1822
buf->range_order.from = query->u.range_query.from;
1823
buf->range_order.to = query->u.range_query.to;
1826
case SB_SQL_QUERY_RANGE_DISTINCT:
1827
stmt = statements[thread_id].range_distinct;
1828
buf->range_distinct.from = query->u.range_query.from;
1829
buf->range_distinct.to = query->u.range_query.to;
1832
case SB_SQL_QUERY_UPDATE_INDEX:
1833
stmt = statements[thread_id].update_index;
1834
buf->update_index.id = query->u.update_query.id;
1837
case SB_SQL_QUERY_UPDATE_NON_INDEX:
1838
stmt = statements[thread_id].update_non_index;
1840
We have to bind non-index update data each time
1841
because of string parameter
1843
snprintf(buf->c, 120, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
1844
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(),
1845
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd());
1846
buf->update_non_index.id = query->u.update_query.id;
1847
buf->c_len = strlen(buf->c);
1848
binds[0].type = DB_TYPE_CHAR;
1849
binds[0].buffer = buf->c;
1850
binds[0].data_len = &buf->c_len;
1851
binds[0].is_null = 0;
1852
binds[0].max_len = 120;
1853
binds[1].type = DB_TYPE_INT;
1854
binds[1].buffer = &buf->update_non_index.id;
1855
binds[1].data_len = 0;
1856
binds[1].is_null = 0;
1857
if (db_bind_param(statements[thread_id].update_non_index, binds, 2))
1861
case SB_SQL_QUERY_DELETE:
1862
stmt = statements[thread_id].delete;
1863
buf->delete.id = query->u.delete_query.id;
1866
case SB_SQL_QUERY_INSERT:
1867
stmt = statements[thread_id].insert;
1868
buf->insert.id = query->u.insert_query.id;
1879
/* Generate SQL statement from query for non-transactional test */
1882
db_stmt_t *get_sql_statement_nontrx(sb_sql_query_t *query, int thread_id)
1884
db_stmt_t *stmt = NULL;
1886
oltp_bind_set_t *buf = bind_bufs + thread_id;
1888
switch (query->type) {
1889
case SB_SQL_QUERY_POINT:
1890
stmt = statements[thread_id].point;
1891
buf->point.id = query->u.point_query.id;
1894
case SB_SQL_QUERY_UPDATE_INDEX:
1895
stmt = statements[thread_id].update_index;
1896
buf->update_index.id = query->u.update_query.id;
1899
case SB_SQL_QUERY_UPDATE_NON_INDEX:
1900
stmt = statements[thread_id].update_non_index;
1902
We have to bind non-index update data each time
1903
because of string parameter
1905
snprintf(buf->c, 120, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
1906
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(),
1907
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd());
1908
buf->update_non_index.id = query->u.update_query.id;
1909
buf->c_len = strlen(buf->c);
1911
binds[0].type = DB_TYPE_CHAR;
1912
binds[0].buffer = buf->c;
1913
binds[0].data_len = &buf->c_len;
1914
binds[0].is_null = 0;
1915
binds[0].max_len = 120;
1917
binds[1].type = DB_TYPE_INT;
1918
binds[1].buffer = &buf->update_non_index.id;
1919
binds[1].data_len = 0;
1920
binds[1].is_null = 0;
1922
if (db_bind_param(statements[thread_id].update_non_index, binds, 2))
1926
case SB_SQL_QUERY_DELETE:
1927
stmt = statements[thread_id].delete;
1928
buf->delete.id = query->u.delete_query.id;
1931
case SB_SQL_QUERY_INSERT:
1932
stmt = statements[thread_id].insert;
1934
We have to bind insert data each time
1935
because of string parameters
1937
buf->range.to = query->u.insert_query.id;
1938
snprintf(buf->c, 120, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
1939
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(),
1940
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd());
1941
buf->c_len = strlen(buf->c);
1942
snprintf(buf->pad, 60, "%d-%d-%d-%d-%d",
1943
sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd(), sb_rnd());
1944
buf->pad_len = strlen(buf->pad);
1946
/* Use NULL is AUTO_INCREMENT is used, unique id otherwise */
1949
binds[0].is_null = &oltp_is_null;
1953
buf->range.from = get_unique_random_id();
1954
binds[0].buffer = &buf->range.from;
1955
binds[0].is_null = 0;
1958
binds[0].type = DB_TYPE_INT;
1959
binds[0].data_len = 0;
1961
binds[1].type = DB_TYPE_INT;
1962
binds[1].buffer = &buf->range.to;
1963
binds[1].data_len = 0;
1964
binds[1].is_null = 0;
1966
binds[2].type = DB_TYPE_CHAR;
1967
binds[2].buffer = buf->c;
1968
binds[2].data_len = &buf->c_len;
1969
binds[2].is_null = 0;
1970
binds[2].max_len = 120;
1972
binds[3].type = DB_TYPE_CHAR;
1973
binds[3].buffer = buf->pad;
1974
binds[3].data_len = &buf->pad_len;
1975
binds[3].is_null = 0;
1976
binds[3].max_len = 60;
1978
if (db_bind_param(statements[thread_id].insert, binds, 4))
1991
/* uniform distribution */
1994
unsigned int rnd_func_uniform(void)
1996
return 1 + sb_rnd() % args.table_size;
2000
/* gaussian distribution */
2003
unsigned int rnd_func_gaussian(void)
2008
for(i=0, sum=0; i < args.dist_iter; i++)
2009
sum += (1 + sb_rnd() % args.table_size);
2011
return sum / args.dist_iter;
2015
/* 'special' distribution */
2018
unsigned int rnd_func_special(void)
2024
unsigned int range_size;
2026
if (args.table_size == 0)
2029
/* Increase range size for special values. */
2030
range_size = args.table_size * (100 / (100 - args.dist_res));
2032
/* Generate evenly distributed one at this stage */
2033
res = (1 + sb_rnd() % range_size);
2035
/* For first part use gaussian distribution */
2036
if (res <= args.table_size)
2038
for(i = 0; i < args.dist_iter; i++)
2040
sum += (1 + sb_rnd() % args.table_size);
2042
return sum / args.dist_iter;
2046
* For second part use even distribution mapped to few items
2047
* We shall distribute other values near by the center
2049
d = args.table_size * args.dist_pct / 100;
2054
/* Now we have res values in SPECIAL_PCT range of the data */
2055
res += (args.table_size / 2 - args.table_size * args.dist_pct / (100 * 2));
2061
/* Generate unique random id */
2064
unsigned int get_unique_random_id(void)
2068
pthread_mutex_lock(&rnd_mutex);
2069
res = (unsigned int) (rnd_seed % args.table_size) + 1;
2070
rnd_seed += LARGE_PRIME;
2071
pthread_mutex_unlock(&rnd_mutex);
2077
int get_think_time(void)
2079
int t = args.user_delay_min;
2081
if (args.user_delay_min < args.user_delay_max)
2082
t += sb_rnd() % (args.user_delay_max - args.user_delay_min);