sql: implement a memory policy that prevents server crashes for large queries#9259
sql: implement a memory policy that prevents server crashes for large queries#9259knz merged 2 commits intocockroachdb:masterfrom
Conversation
1538691 to
f09f94b
Compare
|
haven't looked at any of the clients changed here yet. Let's do one more iteration on the main classes. Review status: 0 of 22 files reviewed at latest revision, 24 unresolved discussions, some commit checks failed. cli/flags.go, line 329 at r1 (raw file):
how are you thinking of flags vs env vars? cli/start.go, line 117 at r1 (raw file):
two space before "again" sql/mon/mem_pool.go, line 35 at r1 (raw file):
add unit here (and I'd add it throughout all params in this file, but I feel most strongly about this one). sql/mon/mem_pool.go, line 51 at r1 (raw file):
nit: to me, sql/mon/mem_pool.go, line 52 at r1 (raw file):
sql/mon/mem_pool.go, line 52 at r1 (raw file):
IMHO, I think for the purposes of this error msg, it's less interesting the amount that's been allocated in the pool, and more interesting what's been already allocated in the sql/mon/mem_pool.go, line 56 at r1 (raw file):
is there a sql/mon/mem_usage.go, line 30 at r1 (raw file):
the "limit" part is wrong, correct (I think it was theoretically doing that before this PR, but not any more?)? And in fact the "tracking" is not really the point of this struct either, is it? It's all about buffering. Maybe we should rename it to... PoolProxy? MemoryBuffer? sql/mon/mem_usage.go, line 38 at r1 (raw file):
As discussed, let's put a much bigger comment here explaining the interactions between Pool - Monitor - Acccount (and probably mention WrappedAccount too) sql/mon/mem_usage.go, line 40 at r1 (raw file):
delete the reference to "in-memory row storage". sql/mon/mem_usage.go, line 44 at r1 (raw file):
is this member actually useful for anything? I'd vote to remove it, particularly since the comment didn't make it clear to me about what it means and I had to look it up. sql/mon/mem_usage.go, line 46 at r1 (raw file):
maybe suggest in this comment how this is going to be used. Otherwise it seems superfluous to me. sql/mon/mem_usage.go, line 50 at r1 (raw file):
is this comment correct? What does "pre-allocated" mean? sql/mon/mem_usage.go, line 53 at r1 (raw file):
maybe expand this comment a bit. Why has any memory been reserved before this was instantiated? Why isn't that memory just set as the initial later: having discussed some, I understand what the deal is. I suggest renaming the field and changing the comment - instead of "already reserved...", say that this is the amount of memory that's never released (maybe call it sql/mon/mem_usage.go, line 59 at r1 (raw file):
make this the first member (to highlight the parent-child structure, and also to celebrate the fact that you've finally embedded a pointer into a struct :) ) sql/mon/mem_usage.go, line 70 at r1 (raw file):
if we call this "hysterisis", I say you rename the "noteworthy" above to "hysterical" sql/mon/mem_usage.go, line 73 at r1 (raw file):
double space sql/mon/mem_usage.go, line 76 at r1 (raw file):
double space sql/mon/mem_usage.go, line 78 at r1 (raw file):
if it's expressed in "blocks", maybe "factor" is not the right name. "Buffer"? sql/mon/mem_usage.go, line 95 at r1 (raw file):
sql/mon/mem_usage.go, line 102 at r1 (raw file):
mmm what about the sql/mon/mem_usage.go, line 164 at r1 (raw file):
rename sql/mon/mem_usage_mutex.go, line 24 at r1 (raw file):
just say it's a thread-safe Monitor. And in the comments of the regular Monitor, say it's not thread-safe and link to this one. sql/mon/mem_usage_mutex.go, line 26 at r1 (raw file):
Do we really need this class? I'd just put a mutex in the other one and call it a thread-safe day. If the mutex is not contended, it shouldn't cost much. Comments from Reviewable |
|
I'm processing these comments bit by bit. Here's a first batch, gimme more time before I address the bigger ones. Review status: 0 of 22 files reviewed at latest revision, 24 unresolved discussions, some commit checks pending. cli/flags.go, line 329 at r1 (raw file):
|
|
Finished the entire first batch of comments, ready for the next one. Review status: 0 of 23 files reviewed at latest revision, 24 unresolved discussions. sql/mon/mem_usage.go, line 30 at r1 (raw file):
|
|
Tobi, you can't just close things that clutter your inbox. |
|
Review status: 0 of 23 files reviewed at latest revision, 10 unresolved discussions, some commit checks failed. sql/mon/mem_pool.go, line 51 at r1 (raw file):
|
|
Review status: 0 of 23 files reviewed at latest revision, 10 unresolved discussions. sql/mon/mem_pool.go, line 51 at r1 (raw file):
|
bbab8ce to
1a2b74f
Compare
|
I have performed the suggested refactorings, and some more. Included in this new revision:
PTAL! |
65f46cb to
90b3db2
Compare
|
Note that I am rebasing this on top of #10094, so I will squash the additional 2 commits after #10094 is merged. Review status: 0 of 39 files reviewed at latest revision, 20 unresolved discussions, all commit checks successful. pkg/cli/flags.go, line 329 at r3 (raw file):
|
b3d5ef1 to
715eabc
Compare
|
PTAL. |
|
nit: I don't think the "admin" and "internal" mem usage should be plotted on the "System Resources" section; just in the Advanced? Looking good man, thanks for working with me. I just suggest a few improvements (IMHO) that I think would be worth-while. Review status: 0 of 41 files reviewed at latest revision, 22 unresolved discussions, some commit checks failed. pkg/cli/flags.go, line 329 at r3 (raw file):
|
9ee3695 to
94b9b30
Compare
|
Indeed I moved the detailed plot to "advanced". Review status: 0 of 40 files reviewed at latest revision, 21 unresolved discussions. pkg/cli/interactive_tests/test_sql_mem_monitor.tcl, line 1 at r7 (raw file):
|
|
🚢 it Review status: 0 of 40 files reviewed at latest revision, 7 unresolved discussions, some commit checks failed. pkg/sql/row_container.go, line 71 at r7 (raw file):
|
…eeds. This patch does what it says on the cover. It also introduces a separate method `handleAuthentication()` on the v3conn object to deal with authentication. This method should overwrite the User in SessionArgs if the protocol exchange decides a new username. As an added benefit this patch also tags logging messages with the authenticated user.
… queries. Prior to this patch, any query that required rows to be loaded in server memory prior to being sent back to the client could cause the server to crash if there is insufficient RAM to store all rows. This patch builds upon the `MemoryUsageMonitor` abstraction (now renamed to `MemoryMonitor`) by enabling chaining/stacking of monitors upon each other. A single `MemoryMonitor` object is shared by all client connections over pgwire. Its capacity for a given node is 25% of total node RAM size, unless overridden via `--max-sql-memory` on that node's `start` command line. Each client connection starts with a budget of 21KiB (configurable via the env. var. `COCKROACH_BASE_SQL_MEMORY_BUDGET`). This budget is pre-reserved from the common pool by the pgwire server (using a pgwire-wide `MemoryMonitor`), and reused when a connection is closed without interacting with the pool. This ensures that the pool is not reached at all for what we expect is common usage: many clients using only OLTP queries returning very few rows (or none) and without need for dynamic server-side row storage. Once a client connection exceeds its pre-reserved budget, its session-bound "root" `MemoryMonitor` starts interacting with the pool by requesting fixed-size chunks. These chunks are 10KiB by default, and this size is configurable via the env. var. `COCKROACH_MEMORY_ALLOCATION_CHUNK_SIZE`. If a session is long-lived, a monitor will relinquish unused memory to the common pool when there are more than 10 unused reserved chunks (this factor is configurable via `COCKROACH_MAX_ALLOCATED_UNUSED_BLOCKS`). Within a session two sub-monitors further detail allocations. The "session monitor" tracks allocations that can span an entire session, for example result sets and prepared statements. The "txn monitor" tracks allocations within transactions. A separate stack of `MemoryMonitor` objects supports SQL allocations by the `adminServer` for UI API calls and admin commands; this is currently unbounded. Another separate stack of monitors also supports allocations by the internal executor (SQL leases, log events, etc.), also unbounded. The various monitor statistics are also aggregated in the admin UI. Finally, the monitors also report to the log files when the total allocation sizes exceeds some threshold. The thresholds are configurable via env vars: - COCKROACH_NOTEWORTHY_SQL_MEMORY_USAGE, default 100MiB Overall SQL allocations by clients. - COCKROACH_NOTEWORTHY_SESSION_MEMORY_USAGE, default 10KiB Allocations by either the session-wide or txn monitor in each session. - COCKROACH_NOTEWORTHY_CONN_MEMORY_USAGE, default 2MiB Upfront reservations by pgwire. - COCKROACH_NOTEWORTHY_INTERNAL_MEMORY_USAGE, default 100KiB Allocations for internal operations (leases, etc.) - COCKROACH_NOTEWORTHY_ADMIN_MEMORY_USAGE, default 100KiB Allocations for queries by the admin UI.
|
Review status: 0 of 40 files reviewed at latest revision, 7 unresolved discussions, some commit checks pending. pkg/sql/row_container.go, line 71 at r7 (raw file):
|


Prior to this patch, any query that required rows to be loaded in
server memory prior to being sent back to the client could cause the
server to crash if there is insufficient RAM to store all rows.
This patch builds upon the
MemoryUsageMonitorabstraction byproviding a new
MemoryPoolobject which serves as a gate toallocations.
A single
MemoryPoolobject is shared by all client connections overpgwire. Its capacity for a given node is 25% of total node RAM size,
unless overridden via
--sql-memoryon that node'sstartcommandline.
Each client connection starts with a budget of 1KiB (configurable via
the env. var.
COCKROACH_BASE_SQL_MEMORY_BUDGET). This budget ispre-reserved from the common pool by the pgwire server (using a
pgwire-wide
MemoryUsageMonitor), and reused when a connection isclosed without interacting with the pool. This ensures that the pool
is not reached at all for what we expect is common usage: many clients
using only OLTP queries returning very few rows (or none) and without
need for dynamic server-side row storage.
Once a client connection exceeds its pre-reserved budget, its
session-bound
MemoryUsageMonitorstarts interacting with the pool byrequesting fixed-size chunks. These chunks are 10KiB by default, and
this size is configurable via the
env. var.
COCKROACH_MEMORY_ALLOCATION_CHUNK_SIZE. If a session islong-lived, a monitor will relinquish unused memory to the common pool
when there are more than 10 unused reserved chunks (this factor is
configurable via
COCKROACH_MEMORY_FREE_FACTOR).A separate
MemoryPoolobject supports SQL allocations by theadminServerfor UI API calls and admin commands; this is currentlyunbounded. Also, allocations by
sql.InternalExecutorare not limitedat all (this uses SQL to obtain leases on descriptors).
Fixes #7572.
This change is