/* File: gr_ryow.c * Name: lefred * Date: 2017-08-05 * Description: Read you own write on Group Replication * proof-of-concept using GTID returned in * OK packet * * Usage: ./gr_ryow [-w ] [-r ] string * * -w: writer node default is localhost * -r: reader node default is localhost * string: the value you want to insert * * gr_ryown insert a record with the inserted value and returns the GTID * of the transaction (from the OK packet). Then it reads data from the * table looking for the value entered but only when the write is applied * (consistent read / read your own read) * It also displays how many milisecond the read took. * * Schema used: sync_test * Table definition: * CREATE TABLE `test` ( * `id` int(11) NOT NULL AUTO_INCREMENT, * `name` varchar(20) DEFAULT NULL, * PRIMARY KEY (`id`), * KEY `name_idx` (`name`) * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 */ #include #include #include #include #include #include void finish_with_error(MYSQL *mysql) { fprintf(stderr, "%s\n", mysql_error(mysql)); mysql_close(mysql); exit(1); } static struct timeval tm1; static inline void start() { gettimeofday(&tm1, NULL); } static inline void stop() { struct timeval tm2; gettimeofday(&tm2, NULL); unsigned long long t = 1000 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec) / 1000; printf("%llu ms\n", t); } int main(int argc, char **argv) { char *s_host_w = "localhost"; char *s_host_r = "localhost"; char s_query[255]; char s_gtid[100]; char *s_value = ""; int opt; MYSQL *mysql = mysql_init(NULL); while ((opt = getopt(argc, argv, "r:w:")) != -1) { switch (opt) { case 'w': s_host_w = optarg; break; case 'r': s_host_r = optarg; break; } } //printf("MySQL client version: %s\n", mysql_get_client_info()); s_value = argv[optind]; if (mysql == NULL) { fprintf(stderr, "%s\n", mysql_error(mysql)); exit(1); } if (mysql_real_connect(mysql, s_host_w, "root", "", "sync_test", 0, NULL, 0) == NULL) { finish_with_error(mysql); } sprintf(s_query, "INSERT INTO test VALUES(0,'%s');", s_value); if (mysql_query(mysql, s_query)) { finish_with_error(mysql); } MYSQL_RES *result = mysql_store_result(mysql); if (result) /* there is a result set to fetch */ { mysql_free_result(result); } else /* there is no result set */ { if (mysql_field_count(mysql) != 0) { fprintf(stderr, "Error %u: %s\n", mysql_errno(mysql), mysql_error(mysql)); } } /* extract any available session state-change information */ enum enum_session_state_type type; for (type = SESSION_TRACK_BEGIN; type <= SESSION_TRACK_END; type++) { const char *data; size_t length; if (mysql_session_track_get_first(mysql, type, &data, &length) == 0) { sprintf(s_gtid,"%*.*s", (int) length, (int) length, data); printf("GTID: %s\n", s_gtid); } } mysql_close(mysql); mysql = mysql_init(NULL); if (mysql_real_connect(mysql, s_host_r, "root", "", "sync_test", 0, NULL, 0) == NULL) { finish_with_error(mysql); } sprintf(s_query, "SELECT WAIT_FOR_EXECUTED_GTID_SET('%s') as `ignore`", s_gtid); //printf("DEBUG: %s\n", s_query); start(); if (mysql_query(mysql, s_query)) { finish_with_error(mysql); } result = mysql_store_result(mysql); mysql_free_result(result); sprintf(s_query, "SELECT id, name FROM test WHERE name = '%s';", s_value); if (mysql_query(mysql, s_query)) { finish_with_error(mysql); } result = mysql_store_result(mysql); if (result) /* there is a result set to fetch */ { mysql_free_result(result); } else /* there is no result set */ { if (mysql_field_count(mysql) != 0) { fprintf(stderr, "Error %u: %s\n", mysql_errno(mysql), mysql_error(mysql)); } } stop(); mysql_close(mysql); exit(0); }