oceanbase

Форк
0
/
ob_index_name_checker.cpp 
485 строк · 17.5 Кб
1
/**
2
 * Copyright (c) 2021 OceanBase
3
 * OceanBase CE is licensed under Mulan PubL v2.
4
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
5
 * You may obtain a copy of Mulan PubL v2 at:
6
 *          http://license.coscl.org.cn/MulanPubL-2.0
7
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
 * See the Mulan PubL v2 for more details.
11
 */
12

13
#define USING_LOG_PREFIX SHARE_SCHEMA
14

15
#include "rootserver/parallel_ddl/ob_index_name_checker.h"
16
#include "share/schema/ob_schema_service_sql_impl.h"
17
#include "share/schema/ob_multi_version_schema_service.h"
18
using namespace oceanbase::lib;
19
using namespace oceanbase::common;
20
using namespace oceanbase::share;
21
using namespace oceanbase::share::schema;
22
using namespace oceanbase::rootserver;
23

24
ObIndexNameCache::ObIndexNameCache(
25
  const uint64_t tenant_id,
26
  common::ObMySQLProxy &sql_proxy)
27
  : mutex_(common::ObLatchIds::IND_NAME_CACHE_LOCK),
28
    tenant_id_(tenant_id),
29
    sql_proxy_(sql_proxy),
30
    allocator_(ObMemAttr(OB_SYS_TENANT_ID, "IndNameInfo", ObCtxIds::SCHEMA_SERVICE)),
31
    cache_(ModulePageAllocator(allocator_)),
32
    loaded_(false)
33
{
34
}
35

36
void ObIndexNameCache::reset_cache()
37
{
38
  lib::ObMutexGuard guard(mutex_);
39
  (void) inner_reset_cache_();
40
}
41

42
void ObIndexNameCache::inner_reset_cache_()
43
{
44
  cache_.destroy();
45
  allocator_.reset();
46
  loaded_ = false;
47
  FLOG_INFO("[INDEX NAME CACHE] reset index name map", K_(tenant_id));
48
}
49

50
int ObIndexNameCache::check_index_name_exist(
51
    const uint64_t tenant_id,
52
    const uint64_t database_id,
53
    const ObString &index_name,
54
    bool &is_exist)
55
{
56
  int ret = OB_SUCCESS;
57
  is_exist = false;
58
  bool is_oracle_mode = false;
59
  if (OB_UNLIKELY(
60
      OB_INVALID_TENANT_ID == tenant_id
61
      || tenant_id_ != tenant_id
62
      || OB_INVALID_ID == database_id
63
      || index_name.empty())) {
64
    ret = OB_INVALID_ARGUMENT;
65
    LOG_WARN("invalid arg", KR(ret), K(tenant_id_), K(tenant_id), K(database_id), K(index_name));
66
  } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
67
             tenant_id, is_oracle_mode))) {
68
    LOG_WARN("fail to check is oracle mode", KR(ret), K(tenant_id));
69
  } else {
70
    lib::ObMutexGuard guard(mutex_);
71
    ObString idx_name;
72
    uint64_t data_table_id = OB_INVALID_ID;
73
    if (OB_FAIL(try_load_cache_())) {
74
      LOG_WARN("fail to load index name cache", KR(ret), K(tenant_id));
75
    } else if (is_recyclebin_database_id(database_id)) {
76
      idx_name = index_name;
77
      data_table_id = OB_INVALID_ID;
78
    } else {
79
      uint64_t data_table_id = ObSimpleTableSchemaV2::extract_data_table_id_from_index_name(index_name);
80
      if (OB_INVALID_ID == database_id) {
81
        ret = OB_INVALID_ARGUMENT;
82
        LOG_WARN("invalid index name", KR(ret), K(index_name));
83
      } else if (OB_FAIL(ObSimpleTableSchemaV2::get_index_name(index_name, idx_name))) {
84
        LOG_WARN("fail to get original index name", KR(ret), K(index_name));
85
      } else {
86
        data_table_id = (is_oracle_mode && !is_mysql_sys_database_id(database_id)) ?
87
                        OB_INVALID_ID : data_table_id;
88
      }
89
    }
90
    if (OB_SUCC(ret)) {
91
      ObIndexSchemaHashWrapper index_name_wrapper(
92
                               tenant_id,
93
                               database_id,
94
                               data_table_id,
95
                               idx_name);
96
      ObIndexNameInfo *index_name_info = NULL;
97
      if (OB_FAIL(cache_.get_refactored(index_name_wrapper, index_name_info))) {
98
        if (OB_HASH_NOT_EXIST == ret) {
99
          ret = OB_SUCCESS;
100
        } else {
101
          LOG_WARN("fail to get index name info", KR(ret), K(index_name_wrapper));
102
        }
103
      } else if (OB_ISNULL(index_name_info)) {
104
        ret = OB_ERR_UNEXPECTED;
105
        LOG_WARN("index name info is null", KR(ret), K(index_name_wrapper));
106
      } else {
107
        is_exist = true;
108
        LOG_INFO("index name exist", KR(ret), KPC(index_name_info),
109
                 K(database_id), K(index_name), K(data_table_id), K(idx_name));
110
        // Before call check_index_name_exist(), index_name will be locked by trans first.
111
        // And add_index_name() will be called before trans commit.
112
        //
113
        // It may has garbage when trans commit failed after add_index_name() is called.
114
        // So, we need to double check if index name actually exists in inner table when confict occurs.
115
        ObSchemaService *schema_service_impl = NULL;
116
        uint64_t index_id = OB_INVALID_ID;
117
        if (OB_ISNULL(schema_service_impl = GSCHEMASERVICE.get_schema_service())) {
118
          ret = OB_ERR_UNEXPECTED;
119
          LOG_WARN("schema service impl is null", KR(ret));
120
        } else if (OB_FAIL(schema_service_impl->get_index_id(
121
                   sql_proxy_, tenant_id, database_id,
122
                   index_name_info->get_index_name(), index_id))) {
123
          LOG_WARN("fail to get index id", KR(ret), KPC(index_name_info));
124
        } else if (OB_INVALID_ID != index_id) {
125
          is_exist = true;
126
        } else {
127
          is_exist = false;
128
          FLOG_INFO("garbage index name exist, should be erased", KPC(index_name_info),
129
                    K(database_id), K(index_name), K(data_table_id), K(idx_name));
130
          if (OB_FAIL(cache_.erase_refactored(index_name_wrapper))) {
131
            LOG_WARN("fail to erase key", KR(ret), K(index_name_wrapper));
132
            if (OB_HASH_NOT_EXIST != ret) {
133
              (void) inner_reset_cache_();
134
            }
135
          }
136
        }
137
      }
138
    }
139
  }
140
  return ret;
141
}
142

143
int ObIndexNameCache::add_index_name(
144
    const share::schema::ObTableSchema &index_schema)
145
{
146
  int ret = OB_SUCCESS;
147
  const uint64_t tenant_id = index_schema.get_tenant_id();
148
  const uint64_t database_id = index_schema.get_database_id();
149
  const ObString &index_name = index_schema.get_table_name_str();
150
  const ObTableType table_type = index_schema.get_table_type();
151
  uint64_t data_table_id = index_schema.get_data_table_id();
152
  bool is_oracle_mode = false;
153
  if (OB_UNLIKELY(
154
      OB_INVALID_TENANT_ID == tenant_id
155
      || tenant_id_ != tenant_id
156
      || OB_INVALID_ID == database_id
157
      || index_name.empty()
158
      || !is_index_table(table_type))) {
159
    ret = OB_INVALID_ARGUMENT;
160
    LOG_WARN("invalid arg", KR(ret), K(tenant_id_),
161
             K(tenant_id), K(database_id), K(index_name), K(table_type));
162
  } else if (OB_UNLIKELY(!is_recyclebin_database_id(database_id)
163
             && index_schema.get_origin_index_name_str().empty())) {
164
    ret = OB_INVALID_ARGUMENT;
165
    LOG_WARN("invalid index schema", KR(ret), K(index_schema));
166
  } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
167
             tenant_id, is_oracle_mode))) {
168
    LOG_WARN("fail to check is oracle mode", KR(ret), K(tenant_id));
169
  } else {
170
    lib::ObMutexGuard guard(mutex_);
171
    if (OB_FAIL(try_load_cache_())) {
172
      LOG_WARN("fail to load index name cache", KR(ret), K(tenant_id));
173
    } else {
174
      void *buf = NULL;
175
      ObIndexNameInfo *index_name_info = NULL;
176
      ObString idx_name;
177
      if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObIndexNameInfo)))) {
178
        ret = OB_ALLOCATE_MEMORY_FAILED;
179
        LOG_WARN("fail to alloc index name info", KR(ret));
180
      } else if (FALSE_IT(index_name_info = new (buf) ObIndexNameInfo())) {
181
      } else if (OB_FAIL(index_name_info->init(allocator_, index_schema))) {
182
        LOG_WARN("fail to init index name info", KR(ret), K(index_schema));
183
      } else if (is_recyclebin_database_id(database_id)) {
184
        data_table_id = OB_INVALID_ID;
185
        idx_name = index_name_info->get_index_name();
186
      } else {
187
        data_table_id = (is_oracle_mode && !is_mysql_sys_database_id(database_id)) ?
188
                        OB_INVALID_ID : index_name_info->get_data_table_id();
189
        idx_name = index_name_info->get_original_index_name();
190
      }
191
      if (OB_SUCC(ret)) {
192
        int overwrite = 0;
193
        ObIndexSchemaHashWrapper index_name_wrapper(index_name_info->get_tenant_id(),
194
                                                    database_id,
195
                                                    data_table_id,
196
                                                    idx_name);
197
        if (OB_FAIL(cache_.set_refactored(index_name_wrapper, index_name_info, overwrite))) {
198
          LOG_WARN("fail to set refactored", KR(ret), KPC(index_name_info));
199
          if (OB_HASH_EXIST == ret) {
200
            ObIndexNameInfo **exist_index_info = cache_.get(index_name_wrapper);
201
            if (OB_NOT_NULL(exist_index_info) && OB_NOT_NULL(*exist_index_info)) {
202
              FLOG_ERROR("[INDEX NAME CACHE] duplicated index info exist",
203
                         KR(ret), KPC(index_name_info), KPC(*exist_index_info));
204
            }
205
          } else {
206
            (void) inner_reset_cache_();
207
          }
208
        } else {
209
          FLOG_INFO("[INDEX NAME CACHE] add index name to cache", KR(ret), KPC(index_name_info));
210
        }
211
      }
212
    }
213
  }
214
  return ret;
215
}
216

217
// need protect by mutex_
218
int ObIndexNameCache::try_load_cache_()
219
{
220
  int ret = OB_SUCCESS;
221
  if (loaded_) {
222
    // do nothing
223
  } else {
224
    (void) inner_reset_cache_();
225

226
    ObRefreshSchemaStatus schema_status;
227
    schema_status.tenant_id_ = tenant_id_;
228
    int64_t schema_version = OB_INVALID_VERSION;
229
    int64_t timeout_ts = OB_INVALID_TIMESTAMP;
230
    if (OB_FAIL(GSCHEMASERVICE.get_schema_version_in_inner_table(
231
        sql_proxy_, schema_status, schema_version))) {
232
      LOG_WARN("fail to get schema version", KR(ret), K(schema_status));
233
    } else if (!ObSchemaService::is_formal_version(schema_version)) {
234
      ret = OB_EAGAIN;
235
      LOG_WARN("schema version is informal, need retry", KR(ret), K(schema_status), K(schema_version));
236
    } else if (OB_FAIL(ObShareUtil::get_ctx_timeout(GCONF.internal_sql_execute_timeout, timeout_ts))) {
237
      LOG_WARN("fail to get timeout", KR(ret));
238
    } else {
239
      int64_t original_timeout_ts = THIS_WORKER.get_timeout_ts();
240
      int64_t schema_version = OB_INVALID_VERSION;
241
      THIS_WORKER.set_timeout_ts(timeout_ts);
242

243
      ObSchemaGetterGuard guard;
244
      int64_t start_time = ObTimeUtility::current_time();
245
      if (OB_FAIL(GSCHEMASERVICE.async_refresh_schema(tenant_id_, schema_version))) {
246
        LOG_WARN("fail to refresh schema", KR(ret), K_(tenant_id), K(schema_version));
247
      } else if (OB_FAIL(GSCHEMASERVICE.get_tenant_schema_guard(tenant_id_, guard))) {
248
        LOG_WARN("fail to get schema guard", KR(ret), K_(tenant_id));
249
      } else if (OB_FAIL(guard.get_schema_version(tenant_id_, schema_version))) {
250
        LOG_WARN("fail to get schema version", KR(ret), K_(tenant_id));
251
      } else if (OB_FAIL(guard.deep_copy_index_name_map(allocator_, cache_))) {
252
        LOG_WARN("fail to deep copy index name map", KR(ret), K_(tenant_id));
253
      } else {
254
        loaded_ = true;
255
        FLOG_INFO("[INDEX NAME CACHE] load index name map", KR(ret), K_(tenant_id),
256
                  K(schema_version), "cost", ObTimeUtility::current_time() - start_time);
257
      }
258

259
      if (OB_FAIL(ret)) {
260
        (void) inner_reset_cache_();
261
        LOG_WARN("load index name map failed", KR(ret), K_(tenant_id),
262
                 K(schema_version), "cost", ObTimeUtility::current_time() - start_time);
263
      }
264

265
      THIS_WORKER.set_timeout_ts(original_timeout_ts);
266
    }
267
  }
268
  return ret;
269
}
270

271
ObIndexNameChecker::ObIndexNameChecker()
272
  : rwlock_(),
273
    allocator_(ObMemAttr(OB_SYS_TENANT_ID, "IndNameCache", ObCtxIds::SCHEMA_SERVICE)),
274
    index_name_cache_map_(),
275
    sql_proxy_(NULL),
276
    inited_(false)
277
{
278
}
279

280
ObIndexNameChecker::~ObIndexNameChecker()
281
{
282
  destroy();
283
}
284

285
int ObIndexNameChecker::init(common::ObMySQLProxy &sql_proxy)
286
{
287
  int ret = OB_SUCCESS;
288
  SpinWLockGuard guard(rwlock_);
289
  if (inited_) {
290
    ret = OB_INIT_TWICE;
291
    LOG_WARN("init twice", KR(ret));
292
  } else {
293
    const int64_t BUCKET_NUM = 1024;
294
    if (OB_FAIL(index_name_cache_map_.create(BUCKET_NUM, "IndNameMap", "IndNameMap"))) {
295
      LOG_WARN("fail to create hash map", KR(ret));
296
    } else {
297
      sql_proxy_ = &sql_proxy;
298
      inited_ = true;
299
    }
300
  }
301
  return ret;
302
}
303

304
void ObIndexNameChecker::destroy()
305
{
306
  SpinWLockGuard guard(rwlock_);
307
  if (inited_) {
308
    FOREACH(it, index_name_cache_map_) {
309
      if (OB_NOT_NULL(it->second)) {
310
        (it->second)->~ObIndexNameCache();
311
        it->second = NULL;
312
      }
313
    }
314
    index_name_cache_map_.destroy();
315
    allocator_.reset();
316
    sql_proxy_ = NULL;
317
    inited_ = false;
318
  }
319
}
320

321
void ObIndexNameChecker::reset_all_cache()
322
{
323
  int ret = OB_SUCCESS;
324
  SpinRLockGuard guard(rwlock_);
325
  if (inited_) {
326
    FOREACH(it, index_name_cache_map_) {
327
      if (OB_NOT_NULL(it->second)) {
328
        (void) (it->second)->reset_cache();
329
      }
330
    }
331
  }
332
}
333

334
int ObIndexNameChecker::reset_cache(const uint64_t tenant_id)
335
{
336
  int ret = OB_SUCCESS;
337
  SpinRLockGuard guard(rwlock_);
338
  if (OB_UNLIKELY(!inited_)) {
339
    ret = OB_NOT_INIT;
340
    LOG_WARN("not init", KR(ret));
341
  } else {
342
    ObIndexNameCache *cache = NULL;
343
    if (OB_FAIL(index_name_cache_map_.get_refactored(tenant_id, cache))) {
344
      if (OB_HASH_NOT_EXIST != ret) {
345
        LOG_WARN("fail to get refactored", KR(ret), K(tenant_id));
346
      } else {
347
        // tenant not in cache, just skip
348
        ret = OB_SUCCESS;
349
      }
350
    } else if (OB_ISNULL(cache)) {
351
      ret = OB_ERR_UNEXPECTED;
352
      LOG_WARN("cache is null", KR(ret), K(tenant_id));
353
    } else {
354
      (void) cache->reset_cache();
355
    }
356
  }
357
  return ret;
358
}
359

360
int ObIndexNameChecker::check_index_name_exist(
361
    const uint64_t tenant_id,
362
    const uint64_t database_id,
363
    const ObString &index_name,
364
    bool &is_exist)
365
{
366
  int ret = OB_SUCCESS;
367
  bool can_skip = false;
368
  is_exist = false;
369
  if (OB_UNLIKELY(!inited_)) {
370
    ret = OB_NOT_INIT;
371
    LOG_WARN("not init", KR(ret));
372
  } else if (OB_FAIL(check_tenant_can_be_skipped_(tenant_id, can_skip))) {
373
    LOG_WARN("fail to check tenant", KR(ret), K(tenant_id));
374
  } else if (can_skip) {
375
    // do nothing
376
  } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
377
             || OB_INVALID_ID == database_id
378
             || index_name.empty())) {
379
    ret = OB_INVALID_ARGUMENT;
380
    LOG_WARN("invalid arg", KR(ret), K(tenant_id), K(database_id), K(index_name));
381
  } else if (OB_FAIL(try_init_index_name_cache_map_(tenant_id))) {
382
    LOG_WARN("fail to init index name cache", KR(ret), K(tenant_id));
383
  } else {
384
    SpinRLockGuard guard(rwlock_);
385
    ObIndexNameCache *cache = NULL;
386
    if (OB_FAIL(index_name_cache_map_.get_refactored(tenant_id, cache))) {
387
      LOG_WARN("fail to get refactored", KR(ret), K(tenant_id));
388
    } else if (OB_ISNULL(cache)) {
389
      ret = OB_ERR_UNEXPECTED;
390
      LOG_WARN("cache is null", KR(ret));
391
    } else if (OB_FAIL(cache->check_index_name_exist(
392
      tenant_id, database_id, index_name, is_exist))) {
393
      LOG_WARN("fail to check index name exist",
394
               KR(ret), K(tenant_id), K(database_id), K(index_name));
395
    }
396
  }
397
  return ret;
398
}
399

400
int ObIndexNameChecker::add_index_name(
401
    const share::schema::ObTableSchema &index_schema)
402
{
403
  int ret = OB_SUCCESS;
404
  const uint64_t tenant_id = index_schema.get_tenant_id();
405
  bool can_skip = false;
406
  if (OB_UNLIKELY(!inited_)) {
407
    ret = OB_NOT_INIT;
408
    LOG_WARN("not init", KR(ret));
409
  } else if (OB_FAIL(check_tenant_can_be_skipped_(tenant_id, can_skip))) {
410
    LOG_WARN("fail to check tenant", KR(ret), K(tenant_id));
411
  } else if (can_skip) {
412
    // do nothing
413
  } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id)) {
414
    ret = OB_INVALID_ARGUMENT;
415
    LOG_WARN("invalid arg", KR(ret), K(tenant_id));
416
  } else if (OB_FAIL(try_init_index_name_cache_map_(tenant_id))) {
417
    LOG_WARN("fail to init index name cache", KR(ret), K(tenant_id));
418
  } else {
419
    SpinRLockGuard guard(rwlock_);
420
    ObIndexNameCache *cache = NULL;
421
    if (OB_FAIL(index_name_cache_map_.get_refactored(tenant_id, cache))) {
422
      LOG_WARN("fail to get refactored", KR(ret), K(tenant_id));
423
    } else if (OB_ISNULL(cache)) {
424
      ret = OB_ERR_UNEXPECTED;
425
      LOG_WARN("cache is null", KR(ret));
426
    } else if (OB_FAIL(cache->add_index_name(index_schema))) {
427
      LOG_WARN("fail to add index name", KR(ret), K(index_schema));
428
    }
429
  }
430
  return ret;
431
}
432

433
// only cache oracle tenant's index name map
434
int ObIndexNameChecker::check_tenant_can_be_skipped_(
435
    const uint64_t tenant_id,
436
    bool &can_skip)
437
{
438
  int ret = OB_SUCCESS;
439
  bool is_oracle_mode = false;
440
  can_skip = false;
441
  if (is_sys_tenant(tenant_id)
442
      || is_meta_tenant(tenant_id)) {
443
    can_skip = true;
444
  } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
445
             tenant_id, is_oracle_mode))) {
446
    LOG_WARN("fail to check is oracle mode", KR(ret), K(tenant_id));
447
  } else {
448
    can_skip = !is_oracle_mode;
449
  }
450
  return ret;
451
}
452

453
int ObIndexNameChecker::try_init_index_name_cache_map_(const uint64_t tenant_id)
454
{
455
  int ret = OB_SUCCESS;
456
  SpinWLockGuard guard(rwlock_);
457
  if (OB_UNLIKELY(!inited_)) {
458
    ret = OB_NOT_INIT;
459
    LOG_WARN("not init", KR(ret));
460
  } else if (OB_ISNULL(sql_proxy_)) {
461
    ret = OB_ERR_UNEXPECTED;
462
    LOG_WARN("sql_proxy is null", KR(ret));
463
  } else {
464
    ObIndexNameCache *cache = NULL;
465
    if (OB_FAIL(index_name_cache_map_.get_refactored(tenant_id, cache))) {
466
      if (OB_HASH_NOT_EXIST != ret) {
467
        LOG_WARN("fail to get cache", KR(ret), K(tenant_id));
468
      } else {
469
        ret = OB_SUCCESS;
470
        cache = NULL;
471
        void *buf = NULL;
472
        if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObIndexNameCache)))) {
473
          ret = OB_ALLOCATE_MEMORY_FAILED;
474
          LOG_WARN("fail to alloc memory", KR(ret));
475
        } else if (FALSE_IT(cache = new (buf) ObIndexNameCache(tenant_id, *sql_proxy_))) {
476
        } else if (OB_FAIL(index_name_cache_map_.set_refactored(tenant_id, cache))) {
477
          LOG_WARN("fail to set cache", KR(ret), K(tenant_id));
478
        }
479
      }
480
    } else {
481
      // cache exist, just skip
482
    }
483
  }
484
  return ret;
485
}
486

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.