|
18 | 18 | #include <ydb/core/kqp/rm_service/kqp_snapshot_manager.h>
|
19 | 19 | #include <ydb/core/ydb_convert/ydb_convert.h>
|
20 | 20 | #include <ydb/core/tx/schemeshard/schemeshard.h>
|
| 21 | +#include <ydb/core/kqp/rm_service/kqp_rm_service.h> |
21 | 22 | #include <ydb/public/lib/operation_id/operation_id.h>
|
22 | 23 |
|
23 | 24 | #include <ydb/core/util/ulid.h>
|
@@ -619,6 +620,23 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
619 | 620 | QueryState->TxId = UlidGen.Next();
|
620 | 621 | QueryState->TxCtx = MakeIntrusive<TKqpTransactionContext>(false, AppData()->FunctionRegistry,
|
621 | 622 | AppData()->TimeProvider, AppData()->RandomProvider, Config->EnableKqpImmediateEffects);
|
| 623 | + |
| 624 | + auto& alloc = QueryState->TxCtx->TxAlloc; |
| 625 | + ui64 mkqlInitialLimit = Settings.MkqlInitialMemoryLimit; |
| 626 | + |
| 627 | + const auto& queryLimitsProto = Settings.TableService.GetQueryLimits(); |
| 628 | + const auto& phaseLimitsProto = queryLimitsProto.GetPhaseLimits(); |
| 629 | + ui64 mkqlMaxLimit = phaseLimitsProto.GetComputeNodeMemoryLimitBytes(); |
| 630 | + mkqlMaxLimit = mkqlMaxLimit ? mkqlMaxLimit : ui64(Settings.MkqlMaxMemoryLimit); |
| 631 | + |
| 632 | + alloc->Alloc.SetLimit(mkqlInitialLimit); |
| 633 | + alloc->Alloc.Ref().SetIncreaseMemoryLimitCallback([this, &alloc, mkqlMaxLimit](ui64 currentLimit, ui64 required) { |
| 634 | + if (required < mkqlMaxLimit) { |
| 635 | + LOG_D("Increase memory limit from " << currentLimit << " to " << required); |
| 636 | + alloc->Alloc.SetLimit(required); |
| 637 | + } |
| 638 | + }); |
| 639 | + |
622 | 640 | QueryState->QueryData = std::make_shared<TQueryData>(QueryState->TxCtx->TxAlloc);
|
623 | 641 | QueryState->TxCtx->SetIsolationLevel(settings);
|
624 | 642 | QueryState->TxCtx->OnBeginQuery();
|
@@ -748,6 +766,8 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
748 | 766 | }
|
749 | 767 | } catch(const yexception& ex) {
|
750 | 768 | ythrow TRequestFail(Ydb::StatusIds::BAD_REQUEST) << ex.what();
|
| 769 | + } catch(const TMemoryLimitExceededException&) { |
| 770 | + ythrow TRequestFail(Ydb::StatusIds::BAD_REQUEST) << BuildMemoryLimitExceptionMessage(); |
751 | 771 | }
|
752 | 772 | return true;
|
753 | 773 | }
|
@@ -2058,6 +2078,9 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
2058 | 2078 | ReplyQueryError(ex.Status, ex.what(), ex.Issues);
|
2059 | 2079 | } catch (const yexception& ex) {
|
2060 | 2080 | InternalError(ex.what());
|
| 2081 | + } catch (const TMemoryLimitExceededException&) { |
| 2082 | + ReplyQueryError(Ydb::StatusIds::INTERNAL_ERROR, |
| 2083 | + BuildMemoryLimitExceptionMessage()); |
2061 | 2084 | }
|
2062 | 2085 | }
|
2063 | 2086 |
|
@@ -2097,6 +2120,9 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
2097 | 2120 | ReplyQueryError(ex.Status, ex.what(), ex.Issues);
|
2098 | 2121 | } catch (const yexception& ex) {
|
2099 | 2122 | InternalError(ex.what());
|
| 2123 | + } catch (const TMemoryLimitExceededException&) { |
| 2124 | + ReplyQueryError(Ydb::StatusIds::UNDETERMINED, |
| 2125 | + BuildMemoryLimitExceptionMessage()); |
2100 | 2126 | }
|
2101 | 2127 | }
|
2102 | 2128 |
|
@@ -2132,14 +2158,24 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
2132 | 2158 | }
|
2133 | 2159 | } catch (const yexception& ex) {
|
2134 | 2160 | InternalError(ex.what());
|
| 2161 | + } catch (const TMemoryLimitExceededException&) { |
| 2162 | + ReplyQueryError(Ydb::StatusIds::INTERNAL_ERROR, |
| 2163 | + BuildMemoryLimitExceptionMessage()); |
2135 | 2164 | }
|
2136 | 2165 | }
|
2137 | 2166 |
|
2138 | 2167 | STATEFN(FinalCleanupState) {
|
2139 |
| - switch (ev->GetTypeRewrite()) { |
2140 |
| - hFunc(TEvents::TEvGone, HandleFinalCleanup); |
2141 |
| - hFunc(TEvents::TEvUndelivered, HandleNoop); |
2142 |
| - hFunc(TEvKqpSnapshot::TEvCreateSnapshotResponse, Handle); |
| 2168 | + try { |
| 2169 | + switch (ev->GetTypeRewrite()) { |
| 2170 | + hFunc(TEvents::TEvGone, HandleFinalCleanup); |
| 2171 | + hFunc(TEvents::TEvUndelivered, HandleNoop); |
| 2172 | + hFunc(TEvKqpSnapshot::TEvCreateSnapshotResponse, Handle); |
| 2173 | + } |
| 2174 | + } catch (const yexception& ex) { |
| 2175 | + InternalError(ex.what()); |
| 2176 | + } catch (const TMemoryLimitExceededException&) { |
| 2177 | + ReplyQueryError(Ydb::StatusIds::INTERNAL_ERROR, |
| 2178 | + BuildMemoryLimitExceptionMessage()); |
2143 | 2179 | }
|
2144 | 2180 | }
|
2145 | 2181 |
|
@@ -2172,6 +2208,15 @@ class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> {
|
2172 | 2208 | }
|
2173 | 2209 | }
|
2174 | 2210 |
|
| 2211 | + TString BuildMemoryLimitExceptionMessage() const { |
| 2212 | + if (QueryState && QueryState->TxCtx) { |
| 2213 | + return TStringBuilder() << "Memory limit exception at " << CurrentStateFuncName() |
| 2214 | + << ", current limit is " << QueryState->TxCtx->TxAlloc->Alloc.GetLimit() << " bytes."; |
| 2215 | + } else { |
| 2216 | + return TStringBuilder() << "Memory limit exception at " << CurrentStateFuncName(); |
| 2217 | + } |
| 2218 | + } |
| 2219 | + |
2175 | 2220 | void ProcessTopicOps(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
|
2176 | 2221 | YQL_ENSURE(ev->Get()->Request);
|
2177 | 2222 | if (ev->Get()->Request->Cookie < QueryId) {
|
|
0 commit comments