28
28
#include " common/signal_handler.h"
29
29
#include " olap/memtable.h"
30
30
#include " olap/rowset/rowset_writer.h"
31
+ #include " olap/storage_engine.h"
31
32
#include " util/debug_points.h"
32
33
#include " util/doris_metrics.h"
33
34
#include " util/metrics.h"
@@ -137,6 +138,37 @@ Status FlushToken::wait() {
137
138
return Status::OK ();
138
139
}
139
140
141
+ Status FlushToken::_try_reserve_memory (QueryThreadContext query_thread_context, int64_t size) {
142
+ auto * thread_context = doris::thread_context ();
143
+ auto * memtable_flush_executor =
144
+ ExecEnv::GetInstance ()->storage_engine ().memtable_flush_executor ();
145
+ Status st;
146
+ do {
147
+ // only try to reserve process memory
148
+ st = thread_context->try_reserve_process_memory (size);
149
+ if (st.ok ()) {
150
+ memtable_flush_executor->inc_flushing_task ();
151
+ break ;
152
+ }
153
+ if (_is_shutdown () || query_thread_context.get_memory_tracker ()->is_query_cancelled ()) {
154
+ st = Status::Cancelled (" flush memtable already cancelled" );
155
+ break ;
156
+ }
157
+ // Make sure at least one memtable is flushing even reserve memory failed.
158
+ if (memtable_flush_executor->check_and_inc_has_any_flushing_task ()) {
159
+ // If there are already any flushing task, Wait for some time and retry.
160
+ LOG_EVERY_T (INFO, 60 ) << fmt::format (
161
+ " Failed to reserve memory {} for flush memtable, retry after 100ms" ,
162
+ PrettyPrinter::print_bytes (size));
163
+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
164
+ } else {
165
+ st = Status::OK ();
166
+ break ;
167
+ }
168
+ } while (true );
169
+ return st;
170
+ }
171
+
140
172
Status FlushToken::_do_flush_memtable (MemTable* memtable, int32_t segment_id, int64_t * flush_size) {
141
173
VLOG_CRITICAL << " begin to flush memtable for tablet: " << memtable->tablet_id ()
142
174
<< " , memsize: " << memtable->memory_usage ()
@@ -147,8 +179,19 @@ Status FlushToken::_do_flush_memtable(MemTable* memtable, int32_t segment_id, in
147
179
SCOPED_ATTACH_TASK (memtable->query_thread_context ());
148
180
signal::set_signal_task_id (_rowset_writer->load_id ());
149
181
signal::tablet_id = memtable->tablet_id ();
182
+
183
+ DEFER_RELEASE_RESERVED ();
184
+
185
+ auto reserve_size = memtable->get_flush_reserve_memory_size ();
186
+ RETURN_IF_ERROR (_try_reserve_memory (memtable->query_thread_context (), reserve_size));
150
187
{
188
+ SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER (
189
+ memtable->query_thread_context ().query_mem_tracker ->write_tracker ());
151
190
SCOPED_CONSUME_MEM_TRACKER (memtable->mem_tracker ());
191
+
192
+ Defer defer {[&]() {
193
+ ExecEnv::GetInstance ()->storage_engine ().memtable_flush_executor ()->dec_flushing_task ();
194
+ }};
152
195
std::unique_ptr<vectorized::Block> block;
153
196
RETURN_IF_ERROR (memtable->to_block (&block));
154
197
RETURN_IF_ERROR (_rowset_writer->flush_memtable (block.get (), segment_id, flush_size));
0 commit comments