Skip to content

Commit 84361c3

Browse files
committed
Exclude users from rows_read counts
This introduces a command line option, `--rows_read_exclude_users=name,name,...` that excludes specified logged-in users from counting against rows read. That excludes rows read from both Insights tracking (i.e., sending a JSON info packet) and server-wide tracking. There is an equivalent `rows-read-exclude-users = name,name,...` key supported in `my.cnf` as well. Checking a user against the exclusion list is moderately expensive -- it parses the string with a for loop and strtok -- so we only do it when creating a new Security_context object, or changing the in an existing Security_context object. That check corresponds with new logins and, for some reason, `USE` statements. The per-row hot path just checks a boolean in the Security_context object, so it's minimal added cost.
1 parent f4d3ddc commit 84361c3

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

sql/auth/sql_security_ctx.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void Security_context::init() {
9393
m_is_skip_grants_user = false;
9494
m_has_drop_policy = false;
9595
m_executed_drop_policy = false;
96+
m_exclude_user_from_rows_read = false;
9697
}
9798

9899
void Security_context::logout() {
@@ -814,6 +815,8 @@ void Security_context::set_user_ptr(const char *user_arg,
814815

815816
// set new user value to m_user.
816817
m_user.set(user_arg, user_arg_length, system_charset_info);
818+
819+
recheck_exclude_rows_read();
817820
}
818821

819822
/**
@@ -836,6 +839,30 @@ void Security_context::assign_user(const char *user_arg,
836839
m_user.copy(user_arg, user_arg_length, system_charset_info);
837840
else
838841
m_user.set((const char *)nullptr, 0, system_charset_info);
842+
843+
recheck_exclude_rows_read();
844+
}
845+
846+
char *rows_read_exclude_users = nullptr;
847+
848+
void Security_context::recheck_exclude_rows_read() {
849+
printf("PIKI: recheck_exclude_rows_read: user=\"%s\"\n", m_user.ptr());
850+
851+
m_exclude_user_from_rows_read = false;
852+
if (rows_read_exclude_users) {
853+
printf("PIKI: rows_read_exclude_users=\"%s\"\n", rows_read_exclude_users);
854+
char *copy = strdup(rows_read_exclude_users);
855+
char *saveptr, *tok;
856+
for (tok=my_strtok_r(copy, ",", &saveptr); tok; tok=my_strtok_r(NULL, ",", &saveptr)) {
857+
printf("PIKI: tok=\"%s\"\n", tok);
858+
if (!strcmp(tok, m_user.ptr())) {
859+
printf("PIKI: yes, exclude them!\n");
860+
m_exclude_user_from_rows_read = true;
861+
break;
862+
}
863+
}
864+
free(copy);
865+
}
839866
}
840867

841868
/**
@@ -879,7 +906,7 @@ void Security_context::set_host_ptr(const char *host_arg,
879906
/**
880907
Setter method for member m_host.
881908
882-
Copies host_arg value to the m_host if it is not null else m_user is set
909+
Copies host_arg value to the m_host if it is not null else m_host is set
883910
to empty string.
884911
885912

sql/auth/sql_security_ctx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Security_context {
6262
void skip_grants(const char *user = "skip-grants user",
6363
const char *host = "skip-grants host");
6464
bool is_skip_grants_user();
65+
bool exclude_user_from_rows_read() const { return m_exclude_user_from_rows_read; }
6566

6667
/**
6768
Getter method for member m_user.
@@ -378,6 +379,9 @@ class Security_context {
378379
*/
379380
bool m_is_skip_grants_user;
380381

382+
bool m_exclude_user_from_rows_read;
383+
void recheck_exclude_rows_read();
384+
381385
bool m_executed_drop_policy;
382386
bool m_has_drop_policy;
383387
std::unique_ptr<std::function<void(Security_context *)>> m_drop_policy;

sql/sys_vars.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,13 @@ static Sys_var_charptr Sys_my_bind_addr(
945945
READ_ONLY NON_PERSIST GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG),
946946
IN_FS_CHARSET, DEFAULT(MY_BIND_ALL_ADDRESSES));
947947

948+
extern char *rows_read_exclude_users;
949+
static Sys_var_charptr Sys_my_rows_read_exclude_users(
950+
"rows_read_exclude_users",
951+
"Comma-separated list of users whose queries do not increment rows_read",
952+
READ_ONLY NON_PERSIST GLOBAL_VAR(rows_read_exclude_users), CMD_LINE(REQUIRED_ARG),
953+
IN_FS_CHARSET, DEFAULT(nullptr));
954+
948955
static Sys_var_charptr Sys_admin_addr(
949956
"admin_address",
950957
"IP address to bind to for service connection. Address can be an IPv4"

storage/innobase/handler/ha_innodb.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9820,7 +9820,7 @@ int ha_innobase::index_read(
98209820
if (m_prebuilt->table->is_system_table) {
98219821
srv_stats.n_system_rows_read.add(
98229822
thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
9823-
} else {
9823+
} else if (!m_user_thd->security_context()->exclude_user_from_rows_read()) {
98249824
srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
98259825
1);
98269826
m_user_thd->get_stmt_da()->inc_rows_read();
@@ -10067,7 +10067,7 @@ int ha_innobase::general_fetch(
1006710067
if (m_prebuilt->table->is_system_table) {
1006810068
srv_stats.n_system_rows_read.add(
1006910069
thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
10070-
} else {
10070+
} else if (!m_user_thd->security_context()->exclude_user_from_rows_read()) {
1007110071
srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
1007210072
1);
1007310073
m_user_thd->get_stmt_da()->inc_rows_read();

0 commit comments

Comments
 (0)