oceanbase
1967 строк · 80.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 RS
14
15#include "ob_root_inspection.h"
16
17#include "lib/string/ob_sql_string.h"
18#include "lib/mysqlclient/ob_mysql_proxy.h"
19#include "lib/utility/ob_tracepoint.h"
20#include "share/inner_table/ob_inner_table_schema.h"
21#include "share/schema/ob_multi_version_schema_service.h"
22#include "share/schema/ob_schema_getter_guard.h"
23#include "share/schema/ob_schema_utils.h"
24#include "share/ob_zone_info.h"
25#include "share/system_variable/ob_system_variable_factory.h"
26#include "share/system_variable/ob_system_variable_init.h"
27#include "rootserver/ob_root_utils.h"
28#include "rootserver/ob_zone_manager.h"
29#include "rootserver/ob_ddl_operator.h"
30#include "rootserver/ob_root_service.h"
31#include "observer/ob_server_struct.h"
32#include "observer/ob_sql_client_decorator.h"
33#include "share/ob_primary_zone_util.h"
34#include "share/ob_upgrade_utils.h"
35#include "share/rc/ob_context.h"
36#include "share/schema/ob_schema_mgr.h"
37#include "share/ob_schema_status_proxy.h"//ObSchemaStatusProxy
38#include "share/ob_global_stat_proxy.h"//ObGlobalStatProxy
39#include "share/ob_tenant_info_proxy.h" // ObAllTenantInfoProxy
40#include "share/schema/ob_table_schema.h"
41
42namespace oceanbase
43{
44using namespace common;
45using namespace common::sqlclient;
46using namespace share;
47using namespace share::schema;
48using namespace sql;
49namespace rootserver
50{
51////////////////////////////////////////////////////////////////
52int ObTenantChecker::inspect(bool &passed, const char* &warning_info)
53{
54int ret = OB_SUCCESS;
55int tmp_ret = OB_SUCCESS;
56passed = true;
57UNUSED(warning_info);
58if (OB_SUCCESS != (tmp_ret = alter_tenant_primary_zone_())) {
59ret = OB_SUCC(ret) ? tmp_ret : ret;
60LOG_WARN("fail to alter tenant primary_zone", KR(ret), KR(tmp_ret));
61}
62
63if (OB_SUCCESS != (tmp_ret = check_create_tenant_end_())) {
64ret = OB_SUCC(ret) ? tmp_ret : ret;
65LOG_WARN("fail to check create tenant end", KR(ret), KR(tmp_ret));
66}
67
68if (OB_SUCCESS != (tmp_ret = check_garbage_tenant_(passed))) {
69ret = OB_SUCC(ret) ? tmp_ret : ret;
70LOG_WARN("fail to check garbage tenant", KR(ret), KR(tmp_ret));
71}
72return ret;
73}
74
75// If the primary_zone of tenant is null, need to set to 'RANDOM'
76int ObTenantChecker::alter_tenant_primary_zone_()
77{
78int ret = OB_SUCCESS;
79ObSchemaGetterGuard schema_guard;
80ObArray<uint64_t> tenant_ids;
81if (OB_ISNULL(schema_service_)) {
82ret = OB_ERR_UNEXPECTED;
83LOG_WARN("schema service not init", K(ret));
84} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
85LOG_WARN("get_schema_guard failed", K(ret));
86} else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) {
87LOG_WARN("get_tenant_ids failed", K(ret));
88} else {
89const ObTenantSchema *tenant_schema = NULL;
90int64_t affected_rows = 0;
91FOREACH_CNT_X(tenant_id, tenant_ids, OB_SUCCESS == ret) {
92if (OB_ISNULL(tenant_id)) {
93ret = OB_ERR_UNEXPECTED;
94LOG_WARN("tenant_id is null", K(ret));
95} else if (OB_FAIL(schema_guard.get_tenant_info(*tenant_id, tenant_schema))) {
96LOG_WARN("fail to get tenant info", K(ret), K(*tenant_id));
97} else if (OB_ISNULL(tenant_schema)) {
98ret = OB_ERR_UNEXPECTED;
99LOG_WARN("tenant schema is null", K(ret), K(*tenant_id));
100} else if (tenant_schema->get_primary_zone().empty()) {
101ObSqlString sql;
102if (OB_FAIL(sql.append_fmt("ALTER TENANT %s set primary_zone = RANDOM",
103tenant_schema->get_tenant_name()))) {
104LOG_WARN("fail to generate sql", K(ret), K(*tenant_id));
105} else if (OB_ISNULL(sql_proxy_)) {
106ret = OB_ERR_UNEXPECTED;
107LOG_WARN("sql_proxy is null", K(ret));
108} else if (OB_FAIL(sql_proxy_->write(sql.ptr(), affected_rows))) {
109LOG_WARN("execute sql failed", K(ret));
110} else {
111ROOTSERVICE_EVENT_ADD("inspector", "alter_tenant_primary_zone",
112"tenant_id", tenant_schema->get_tenant_id(),
113"tenant", tenant_schema->get_tenant_name());
114}
115}
116}
117}
118return ret;
119}
120
121int ObTenantChecker::check_create_tenant_end_()
122{
123int ret = OB_SUCCESS;
124ObSchemaGetterGuard schema_guard;
125ObArray<uint64_t> tenant_ids;
126if (OB_ISNULL(schema_service_)) {
127ret = OB_ERR_UNEXPECTED;
128LOG_WARN("schema service not init", K(ret));
129} else if (!schema_service_->is_sys_full_schema()) {
130// skip
131} else if (GCTX.is_standby_cluster()) {
132// skip
133} else if (OB_FAIL(schema_service_->get_tenant_ids(tenant_ids))) {
134LOG_WARN("get_tenant_ids failed", K(ret));
135} else if (OB_ISNULL(GCTX.root_service_)) {
136ret = OB_ERR_UNEXPECTED;
137LOG_WARN("rootservice is null", KR(ret));
138} else {
139const ObSimpleTenantSchema *tenant_schema = NULL;
140int64_t schema_version = OB_INVALID_VERSION;
141int64_t baseline_schema_version = OB_INVALID_VERSION;
142FOREACH_CNT(tenant_id, tenant_ids) {
143// overwrite ret
144if (!GCTX.root_service_->is_full_service()) {
145ret = OB_CANCELED;
146LOG_WARN("rs is not in full service", KR(ret));
147break;
148} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(*tenant_id, schema_guard))) {
149LOG_WARN("get_schema_guard failed", KR(ret), K(*tenant_id));
150} else if (OB_FAIL(schema_guard.get_schema_version(*tenant_id, schema_version))) {
151LOG_WARN("fail to get tenant schema version", KR(ret), K(*tenant_id));
152} else if (!share::schema::ObSchemaService::is_formal_version(schema_version)) {
153// tenant is still in creating
154} else if (OB_FAIL(schema_guard.get_tenant_info(*tenant_id, tenant_schema))) {
155LOG_WARN("fail to get tenant schema", KR(ret), K(*tenant_id));
156} else if (OB_ISNULL(tenant_schema)) {
157ret = OB_ERR_UNEXPECTED;
158LOG_WARN("tenant not exist", KR(ret), K(*tenant_id));
159} else if (OB_FAIL(schema_service_->get_baseline_schema_version(*tenant_id, false/*auto update*/,
160baseline_schema_version))) {
161LOG_WARN("fail to get baseline schema_version", KR(ret), K(*tenant_id));
162} else if (OB_INVALID_VERSION == baseline_schema_version) {
163//baseline_schema_version is not valid, just skip to create this kind of tenant
164} else if (tenant_schema->is_creating()) {
165obrpc::ObCreateTenantEndArg arg;
166arg.exec_tenant_id_ = OB_SYS_TENANT_ID;
167arg.tenant_id_ = *tenant_id;
168if (OB_FAIL(rpc_proxy_.create_tenant_end(arg))) {
169LOG_WARN("fail to execute create tenant end", KR(ret), K(*tenant_id));
170} else {
171LOG_INFO("execute create_tenant_end", KR(ret), K(*tenant_id), K(schema_version));
172ROOTSERVICE_EVENT_ADD("inspector", "tenant_checker", "info", "execute create_tenant_end", "tenant_id", *tenant_id);
173}
174}
175}
176}
177return ret;
178}
179
180int ObTenantChecker::check_garbage_tenant_(bool &passed)
181{
182int ret = OB_SUCCESS;
183if (OB_ISNULL(schema_service_)) {
184ret = OB_ERR_UNEXPECTED;
185LOG_WARN("schema service not init", KR(ret));
186} else if (!schema_service_->is_sys_full_schema()) {
187// skip
188} else {
189obrpc::ObGetSchemaArg arg;
190obrpc::ObTenantSchemaVersions result;
191ObSchemaGetterGuard schema_guard;
192arg.ignore_fail_ = true;
193arg.exec_tenant_id_ = OB_SYS_TENANT_ID;
194const int64_t rpc_timeout = GCONF.rpc_timeout * 10;
195// There may have multi RootService, so we won't force drop tenant here.
196if (OB_FAIL(rpc_proxy_.timeout(rpc_timeout).get_tenant_schema_versions(arg, result))) {
197LOG_WARN("fail to get tenant schema versions", KR(ret));
198} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
199LOG_WARN("get_schema_guard failed", KR(ret));
200}
201for (int64_t i = 0; OB_SUCC(ret) && i < result.tenant_schema_versions_.count(); i++) {
202TenantIdAndSchemaVersion &tenant = result.tenant_schema_versions_.at(i);
203int tmp_ret = OB_SUCCESS;
204if (!GCTX.root_service_->is_full_service()) {
205ret = OB_CANCELED;
206LOG_WARN("rs is not in full service", KR(ret));
207} else if (!ObSchemaService::is_formal_version(tenant.schema_version_)) {
208const ObSimpleTenantSchema *tenant_schema = NULL;
209uint64_t tenant_id = tenant.tenant_id_;
210if (OB_SUCCESS != (tmp_ret = schema_guard.get_tenant_info(tenant_id, tenant_schema))) {
211LOG_WARN("fail to get tenant info", KR(tmp_ret), K(tenant_id));
212} else if (OB_ISNULL(tenant_schema)) {
213tmp_ret = OB_TENANT_NOT_EXIST;
214} else if (tenant_schema->is_restore()) {
215LOG_INFO("tenant is in restore", KPC(tenant_schema));
216} else if (tenant_schema->is_creating()) {
217LOG_ERROR("the tenant may be in the process of creating, if the error reports continuously, please check", K(tenant_id));
218LOG_DBA_WARN(OB_ERR_ROOT_INSPECTION, "msg", "the tenant may be in the process of creating, if the error reports continuously, please check",
219K(tenant_id), "tenant_name", tenant_schema->get_tenant_name());
220ROOTSERVICE_EVENT_ADD("inspector", "tenant_checker",
221"info", "the tenant may be in the process of creating, if the error reports continuously, please check",
222"tenant_id", tenant_id,
223"tenant_name", tenant_schema->get_tenant_name_str());
224}
225ret = OB_SUCC(ret) ? tmp_ret : ret;
226}
227} // end for
228passed = OB_SUCC(ret);
229}
230return ret;
231}
232
233////////////////////////////////////////////////////////////////
234ObTableGroupChecker::ObTableGroupChecker(share::schema::ObMultiVersionSchemaService &schema_service)
235: schema_service_(schema_service),
236check_part_option_map_(),
237part_option_not_match_set_(),
238allocator_(ObModIds::OB_SCHEMA),
239is_inited_(false)
240{
241}
242
243int ObTableGroupChecker::init()
244{
245int ret = OB_SUCCESS;
246if (is_inited_) {
247ret = OB_INIT_TWICE;
248LOG_WARN("init twice", K(ret));
249} else if (OB_FAIL(check_part_option_map_.create(TABLEGROUP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_TABLEGROUP_MAP))) {
250LOG_WARN("init check_part_option_map failed", K(ret));
251} else if (OB_FAIL(part_option_not_match_set_.create(TABLEGROUP_BUCKET_NUM))) {
252LOG_WARN("init part_option_not_match_set failed", K(ret));
253} else {
254is_inited_ = true;
255}
256return ret;
257}
258
259ObTableGroupChecker::~ObTableGroupChecker()
260{
261}
262
263int ObTableGroupChecker::inspect(bool &passed, const char* &warning_info)
264{
265int ret = OB_SUCCESS;
266passed = true;
267ObArray<uint64_t> tenant_ids;
268if (!is_inited_) {
269ret = OB_NOT_INIT;
270LOG_WARN("tablegroup checker is not init", K(ret));
271} else if (OB_FAIL(schema_service_.get_tenant_ids(tenant_ids))) {
272LOG_WARN("fail to get tenant ids", KR(ret));
273} else {
274int tmp_ret = OB_SUCCESS;
275FOREACH(tenant_id, tenant_ids) { // ignore error for each tenant
276if (OB_SUCCESS != (tmp_ret = inspect_(*tenant_id, passed))) {
277LOG_WARN("inspect tablegroup options by tenant failed",
278KR(tmp_ret), "tenant_id", *tenant_id);
279}
280ret = OB_SUCC(ret) ? tmp_ret : ret;
281}
282if (!passed) {
283warning_info = "tablegroup has tables that have different primary_zone/locality/part_option";
284}
285}
286return ret;
287}
288
289int ObTableGroupChecker::inspect_(
290const uint64_t tenant_id,
291bool &passed)
292{
293int ret = OB_SUCCESS;
294ObSchemaGetterGuard schema_guard;
295allocator_.reset();
296check_part_option_map_.reuse();
297part_option_not_match_set_.reuse();
298ObArray<uint64_t> table_ids;
299if (!is_inited_) {
300ret = OB_NOT_INIT;
301LOG_WARN("tablegroup checker is not init", KR(ret));
302} else if (OB_FAIL(schema_service_.get_tenant_schema_guard(tenant_id, schema_guard))) {
303LOG_WARN("get schema guard failed", KR(ret), K(tenant_id));
304} else if (OB_FAIL(schema_guard.get_table_ids_in_tenant(tenant_id, table_ids))) {
305LOG_WARN("fail to get table_ids", KR(ret), K(tenant_id));
306} else if (OB_ISNULL(GCTX.root_service_)) {
307ret = OB_ERR_UNEXPECTED;
308LOG_WARN("rootservice is null", KR(ret));
309} else if (!GCTX.root_service_->is_full_service()) {
310ret = OB_CANCELED;
311LOG_WARN("rs is not in full service", KR(ret));
312} else {
313for (int64_t i = 0; OB_SUCC(ret) && i < table_ids.count(); i++) {
314const uint64_t table_id = table_ids.at(i);
315const ObTableSchema *table = NULL;
316// schema guard cannot be used repeatedly in iterative logic,
317// otherwise it will cause a memory hike in schema cache
318if (!GCTX.root_service_->is_full_service()) {
319ret = OB_CANCELED;
320LOG_WARN("rs is not in full service", KR(ret));
321} else if (OB_FAIL(schema_service_.get_tenant_schema_guard(tenant_id, schema_guard))) {
322LOG_WARN("get schema guard failed", K(ret), K(tenant_id));
323} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id, table_id, table))) {
324LOG_WARN("get table schema failed", K(ret), KT(table_id));
325} else if (OB_ISNULL(table)) {
326ret = OB_ERR_UNEXPECTED;
327LOG_WARN("table not exist", KR(ret), K(table_id));
328} else if (is_sys_table(table->get_table_id()) || !table->has_partition()) {
329// skip, check the partitioned user table
330} else if (OB_FAIL(check_part_option(*table, schema_guard))) {
331LOG_WARN("check part option fail", KR(ret), KPC(table));
332} else {}
333}
334}
335if (OB_SUCC(ret)) {
336if (part_option_not_match_set_.size() > 0) {
337passed = false;
338LOG_WARN("tables part option in one tablegroup are not the same", K(tenant_id), K_(part_option_not_match_set));
339ROOTSERVICE_EVENT_ADD("inspector", "check_part_option", K(tenant_id), K_(part_option_not_match_set));
340}
341}
342return ret;
343}
344
345// Check the partition_option of tables in the same tablegroup:
346// 1. For tablegroups created before 2.0, the part_type and part_num of tables in tablegroup should be same.
347// 2. For tablegroups created after 2.0:
348// 1) tablegroup is nonpartition, Allow "non partitioned table" or "partitioned table with 1 number of partitions" in tablegroup.
349// in addition, the partition_num, partition_type, partition_value and number of expression vectors of tables must be same.
350// 2) tablegroup is partitioned, the partition_num, partition_type, partition_value and number of expression vectors
351// of tables in tablegroup should be same.
352int ObTableGroupChecker::check_part_option(const ObSimpleTableSchemaV2 &table, ObSchemaGetterGuard &schema_guard)
353{
354int ret = OB_SUCCESS;
355int tmp_ret = OB_SUCCESS;
356ObSqlString user_error;
357const uint64_t tenant_id = table.get_tenant_id();
358const uint64_t tablegroup_id = table.get_tablegroup_id();
359if (!is_inited_) {
360ret = OB_NOT_INIT;
361LOG_WARN("tablegroup checker is not init", KR(ret));
362} else if (OB_INVALID_ID == tablegroup_id) {
363// skip check while tablegroup_id is default value
364} else if (!table.is_user_table()) {
365// only check user table
366} else if (OB_HASH_NOT_EXIST != (tmp_ret = part_option_not_match_set_.exist_refactored(tablegroup_id))) {
367//skip check while already in part_option_not_match_set_
368if (OB_HASH_EXIST != tmp_ret) {
369ret = tmp_ret;
370LOG_WARN("fail to check if tablegroup_id exist", KR(ret), K(tablegroup_id));
371}
372} else {
373const ObSimpleTableSchemaV2 *table_in_map = NULL;
374bool is_matched = true;
375const ObTablegroupSchema *tablegroup = NULL;
376const ObSimpleTableSchemaV2 *primary_table_schema = NULL;
377if (OB_FAIL(schema_guard.get_tablegroup_schema(tenant_id, tablegroup_id, tablegroup))) {
378LOG_WARN("fail to get tablegroup schema", KR(ret), K(tenant_id), KT(tablegroup_id));
379} else if (OB_ISNULL(tablegroup)) {
380ret = OB_ERR_UNEXPECTED;
381LOG_WARN("tablegroup schema is null", KR(ret), KT(tablegroup_id));
382} else if (tablegroup->get_sharding() == OB_PARTITION_SHARDING_NONE) {
383//no need to check,just ignore
384} else if (tablegroup->get_sharding() == OB_PARTITION_SHARDING_PARTITION
385|| tablegroup->get_sharding() == OB_PARTITION_SHARDING_ADAPTIVE) {
386bool check_sub_part = tablegroup->get_sharding() == OB_PARTITION_SHARDING_PARTITION ? false : true;
387if (OB_FAIL(check_part_option_map_.get_refactored(tablegroup_id, table_in_map))) {
388//set to the map while not in check_part_option_map_
389if (OB_HASH_NOT_EXIST == ret) {
390ObSimpleTableSchemaV2 *new_table_schema = NULL;
391if (OB_FAIL(schema_guard.get_primary_table_schema_in_tablegroup(tenant_id, tablegroup_id, primary_table_schema))) {
392LOG_WARN("fail to get primary table schema in tablegroup", KR(ret), K(tablegroup_id));
393} else if (OB_ISNULL(primary_table_schema)) {
394ret = OB_ERR_UNEXPECTED;
395LOG_WARN("primary table schema is NULL", KR(ret), K(tenant_id), K(tablegroup_id));
396} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, *primary_table_schema, new_table_schema))) {
397LOG_WARN("alloc schema failed", KR(ret), KPC(primary_table_schema));
398} else if (OB_FAIL(check_part_option_map_.set_refactored(tablegroup_id, new_table_schema))) {
399LOG_WARN("set table_schema in hashmap fail", KR(ret), K(tablegroup_id), KPC(primary_table_schema));
400}
401} else {
402LOG_WARN("check tablegroup_id in hashmap fail", KR(ret), K(tablegroup_id));
403}
404} else if (OB_ISNULL(table_in_map)) {
405ret = OB_ERR_UNEXPECTED;
406LOG_WARN("table_is_map is NULL", KR(ret), K(tablegroup_id));
407} else if (OB_FAIL(ObSimpleTableSchemaV2::compare_partition_option(table, *table_in_map, check_sub_part, is_matched, &user_error))) {
408LOG_WARN("fail to check partition option", KR(ret), K(table), KPC(table_in_map));
409}
410} else {
411ret = OB_ERR_UNEXPECTED;
412LOG_WARN("sharding type not suit", KR(ret), KPC(tablegroup));
413}
414if (OB_FAIL(ret) || is_matched) {
415//skip
416} else if (OB_FAIL(part_option_not_match_set_.set_refactored(tablegroup_id))) {
417LOG_WARN("set tablegroup_id in hashset fail", KR(ret));
418} else if (OB_ISNULL(table_in_map)) {
419ret = OB_ERR_UNEXPECTED;
420LOG_WARN("table_is_map is NULL", KR(ret), K(tablegroup_id));
421} else {
422LOG_INFO("tables in one tablegroup have different part/subpart option",
423K(tablegroup_id), "table_id", table.get_table_id(), K(user_error), K(table_in_map->get_table_id()));
424}
425}
426return ret;
427}
428
429////////////////////////////////////////////////////////////////
430ObInspector::ObInspector(ObRootService &rs)
431:ObAsyncTimerTask(rs.get_inspect_task_queue()),
432rs_(rs)
433{}
434
435int ObInspector::process()
436{
437// @todo ObTaskController::get().switch_task(share::ObTaskType::ROOT_SERVICE);
438int ret = OB_SUCCESS;
439ObTableGroupChecker tablegroup_checker(rs_.get_schema_service());
440ObRootInspection system_schema_checker;
441ObTenantChecker tenant_checker(rs_.get_schema_service(), rs_.get_sql_proxy(), rs_.get_common_rpc_proxy());
442
443ret = OB_E(EventTable::EN_STOP_ROOT_INSPECTION) OB_SUCCESS;
444if (OB_FAIL(ret)) {
445} else if (OB_FAIL(tablegroup_checker.init())) {
446LOG_WARN("init tablegroup_checker failed", K(ret));
447} else if (OB_FAIL(system_schema_checker.init(rs_.get_schema_service(), rs_.get_zone_mgr(),
448rs_.get_sql_proxy()))) {
449LOG_WARN("init root inspection failed", K(ret));
450} else {
451ObInspectionTask *inspection_tasks[] = {
452&tablegroup_checker,
453&system_schema_checker,
454&tenant_checker
455};
456bool passed = true;
457const char* warning_info = NULL;
458int N = ARRAYSIZEOF(inspection_tasks);
459for (int i = 0; i < N; ++i) {
460passed = true;
461warning_info = NULL;
462int tmp_ret = inspection_tasks[i]->inspect(passed, warning_info);
463if (OB_SUCCESS != tmp_ret) {
464LOG_WARN("inpection task failed", K(tmp_ret), K(i), "task", inspection_tasks[i]->get_task_name());
465} else if (passed) {
466LOG_INFO("inspection task succ", K(i), "task", inspection_tasks[i]->get_task_name());
467} else {
468LOG_ERROR(warning_info);
469ROOTSERVICE_EVENT_ADD("inspector", inspection_tasks[i]->get_task_name(),
470"info", (warning_info == NULL ? "": warning_info));
471}
472}
473}
474return ret;
475}
476
477ObAsyncTask *ObInspector::deep_copy(char *buf, const int64_t buf_size) const
478{
479ObInspector *task = NULL;
480if (NULL == buf || buf_size < static_cast<int64_t>(sizeof(*this))) {
481LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size));
482} else {
483task = new(buf) ObInspector(rs_);
484}
485return task;
486}
487
488////////////////////////////////////////////////////////////////
489ObPurgeRecyclebinTask::ObPurgeRecyclebinTask(ObRootService &rs)
490:ObAsyncTimerTask(rs.get_inspect_task_queue()),
491root_service_(rs)
492{}
493
494int ObPurgeRecyclebinTask::process()
495{
496LOG_INFO("purge recyclebin task begin");
497int ret = OB_SUCCESS;
498const int64_t PURGE_EACH_TIME = 1000;
499int64_t delay = 1 * 60 * 1000 * 1000;
500int64_t expire_time = GCONF.recyclebin_object_expire_time;
501int64_t purge_interval = GCONF._recyclebin_object_purge_frequency;
502if (expire_time > 0 && purge_interval > 0) {
503if (OB_FAIL(root_service_.purge_recyclebin_objects(PURGE_EACH_TIME))) {
504LOG_WARN("fail to purge recyclebin objects", KR(ret));
505}
506delay = purge_interval;
507}
508// the error code is only for outputtion log, the function will return success.
509// the task no need retry, because it will be triggered periodically.
510if (OB_FAIL(root_service_.schedule_recyclebin_task(delay))) {
511LOG_WARN("schedule purge recyclebin task failed", KR(ret), K(delay));
512} else {
513LOG_INFO("submit purge recyclebin task success", K(delay));
514}
515LOG_INFO("purge recyclebin task end", K(delay));
516return OB_SUCCESS;
517}
518
519ObAsyncTask *ObPurgeRecyclebinTask::deep_copy(char *buf, const int64_t buf_size) const
520{
521ObPurgeRecyclebinTask *task = NULL;
522if (NULL == buf || buf_size < static_cast<int64_t>(sizeof(*this))) {
523LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size));
524} else {
525task = new(buf) ObPurgeRecyclebinTask(root_service_);
526}
527return task;
528}
529
530ObRootInspection::ObRootInspection()
531: inited_(false), stopped_(false), zone_passed_(false),
532sys_param_passed_(false), sys_stat_passed_(false),
533sys_table_schema_passed_(false), data_version_passed_(false),
534all_checked_(false), all_passed_(false), can_retry_(false),
535sql_proxy_(NULL), rpc_proxy_(NULL), schema_service_(NULL),
536zone_mgr_(NULL)
537{
538}
539
540ObRootInspection::~ObRootInspection()
541{
542}
543
544int ObRootInspection::init(ObMultiVersionSchemaService &schema_service,
545ObZoneManager &zone_mgr,
546ObMySQLProxy &sql_proxy,
547obrpc::ObCommonRpcProxy *rpc_proxy)
548{
549int ret = OB_SUCCESS;
550if (inited_) {
551ret = OB_INIT_TWICE;
552LOG_WARN("init twice", K(ret));
553} else {
554schema_service_ = &schema_service;
555zone_mgr_ = &zone_mgr;
556sql_proxy_ = &sql_proxy;
557stopped_ = false;
558zone_passed_ = false;
559sys_param_passed_ = false;
560sys_stat_passed_ = false;
561sys_table_schema_passed_ = false;
562data_version_passed_ = false;
563all_checked_ = false;
564all_passed_ = false;
565can_retry_ = false;
566rpc_proxy_ = rpc_proxy;
567inited_ = true;
568}
569return ret;
570}
571
572int ObRootInspection::check_all()
573{
574int ret = OB_SUCCESS;
575if (!inited_) {
576ret = OB_NOT_INIT;
577LOG_WARN("not init", K(ret));
578} else if (OB_FAIL(check_cancel())) {
579LOG_WARN("check_cancel failed", K(ret));
580} else if (OB_ISNULL(schema_service_)) {
581ret = OB_ERR_UNEXPECTED;
582LOG_WARN("schema_service is null", K(ret));
583} else if (!schema_service_->is_tenant_full_schema(OB_SYS_TENANT_ID)) {
584ret = OB_EAGAIN;
585LOG_WARN("schema is not ready, try again", K(ret));
586} else {
587can_retry_ = false;
588int tmp = OB_SUCCESS;
589
590// check __all_zone
591if (OB_SUCCESS != (tmp = check_zone())) {
592LOG_WARN("check_zone failed", K(tmp));
593ret = (OB_SUCCESS == ret) ? tmp : ret;
594}
595zone_passed_ = (OB_SUCCESS == tmp);
596
597// check sys stat
598tmp = OB_SUCCESS;
599if (OB_SUCCESS != (tmp = check_sys_stat_())) {
600LOG_WARN("check_sys_stat failed", K(tmp));
601ret = (OB_SUCCESS == ret) ? tmp : ret;
602}
603sys_stat_passed_ = (OB_SUCCESS == tmp);
604
605// check sys param
606tmp = OB_SUCCESS;
607if (OB_SUCCESS != (tmp = check_sys_param_())) {
608LOG_WARN("check_sys_param failed", K(tmp));
609ret = (OB_SUCCESS == ret) ? tmp : ret;
610}
611sys_param_passed_ = (OB_SUCCESS == tmp);
612
613// check sys schema
614tmp = OB_SUCCESS;
615if (OB_SUCCESS != (tmp = check_sys_table_schemas_())) {
616LOG_WARN("check_sys_table_schemas failed", K(tmp));
617ret = (OB_SUCCESS == ret) ? tmp : ret;
618}
619sys_table_schema_passed_ = (OB_SUCCESS == tmp);
620
621// check tenant's data version
622tmp = OB_SUCCESS;
623if (OB_SUCCESS != (tmp = check_data_version_())) {
624LOG_WARN("check_data_version failed", K(tmp));
625ret = (OB_SUCCESS == ret) ? tmp : ret;
626}
627data_version_passed_ = (OB_SUCCESS == tmp);
628
629// upgrade job may still running, in order to avoid the upgrade process error stuck,
630// ignore the 4674 error
631for (int64_t i = 0; i < UPGRADE_JOB_TYPE_COUNT; i++) {
632tmp = OB_SUCCESS;
633ObRsJobType job_type = upgrade_job_type_array[i];
634if (job_type > JOB_TYPE_INVALID && job_type < JOB_TYPE_MAX) {
635if (OB_SUCCESS != (tmp = check_cancel())) {
636LOG_WARN("check_cancel failed", KR(ret), K(tmp));
637ret = (OB_SUCCESS == ret) ? tmp : ret;
638break;
639} else if (OB_SUCCESS != (tmp = ObUpgradeUtils::check_upgrade_job_passed(job_type))) {
640LOG_WARN("fail to check upgrade job passed", K(tmp), K(job_type));
641if (OB_RUN_JOB_NOT_SUCCESS != tmp) {
642ret = (OB_SUCCESS == ret) ? tmp : ret;
643} else {
644LOG_WARN("upgrade job may still running, check with __all_virtual_uprade_inspection",
645K(ret), K(tmp), "job_type", ObRsJobTableOperator::get_job_type_str(job_type));
646}
647}
648}
649}
650
651all_checked_ = true;
652all_passed_ = OB_SUCC(ret);
653}
654return ret;
655}
656
657int ObRootInspection::check_tenant(const uint64_t tenant_id)
658{
659int ret = OB_SUCCESS;
660if (!inited_) {
661ret = OB_NOT_INIT;
662LOG_WARN("not init", KR(ret));
663} else if (OB_FAIL(check_cancel())) {
664LOG_WARN("check_cancel failed", KR(ret));
665} else {
666int tmp_ret = OB_SUCCESS;
667if (OB_TMP_FAIL(check_sys_stat_(tenant_id))) {
668LOG_WARN("fail to check sys stat", KR(tmp_ret), K(tenant_id));
669ret = OB_SUCC(ret) ? tmp_ret : ret;
670}
671if (OB_TMP_FAIL(check_sys_param_(tenant_id))) {
672LOG_WARN("fail to check param", KR(tmp_ret), K(tenant_id));
673ret = OB_SUCC(ret) ? tmp_ret : ret;
674}
675if (OB_TMP_FAIL(check_sys_table_schemas_(tenant_id))) {
676LOG_WARN("fail to check sys table", KR(tmp_ret), K(tenant_id));
677ret = OB_SUCC(ret) ? tmp_ret : ret;
678}
679}
680return ret;
681}
682
683int ObRootInspection::inspect(bool &passed, const char* &warning_info)
684{
685int ret = OB_SUCCESS;
686if (!GCONF.in_upgrade_mode()) {
687ret = check_all();
688if (OB_SUCC(ret)) {
689passed = all_passed_;
690warning_info = "system metadata error";
691}
692} else {
693passed = true;
694}
695return ret;
696}
697
698
699// standby tenant may stay at lower data version,
700// root_inspection won't check standby tenant's schema.
701int ObRootInspection::construct_tenant_ids_(
702common::ObIArray<uint64_t> &tenant_ids)
703{
704int ret = OB_SUCCESS;
705tenant_ids.reset();
706ObArray<uint64_t> standby_tenants;
707ObArray<uint64_t> tmp_tenants;
708if (!inited_) {
709ret = OB_NOT_INIT;
710LOG_WARN("not init", KR(ret));
711} else if (OB_FAIL(check_cancel())) {
712LOG_WARN("check_cancel failed", KR(ret));
713} else if (OB_FAIL(ObTenantUtils::get_tenant_ids(schema_service_, tmp_tenants))) {
714LOG_WARN("get_tenant_ids failed", KR(ret));
715} else {
716bool is_standby = false;
717for (int64_t i = 0; OB_SUCC(ret) && i < tmp_tenants.count(); i++) {
718const uint64_t tenant_id = tmp_tenants.at(i);
719if (OB_FAIL(ObAllTenantInfoProxy::is_standby_tenant(sql_proxy_, tenant_id, is_standby))) {
720LOG_WARN("fail to check is standby tenant", KR(ret), K(tenant_id));
721} else if (is_standby) {
722// skip
723} else if (OB_FAIL(tenant_ids.push_back(tenant_id))) {
724LOG_WARN("fail to push back tenant_id", KR(ret), K(tenant_id));
725}
726} // end for
727}
728return ret;
729}
730
731int ObRootInspection::check_zone()
732{
733int ret = OB_SUCCESS;
734ObSqlString extra_cond;
735HEAP_VAR(ObGlobalInfo, global_zone_info) {
736ObArray<ObZoneInfo> zone_infos;
737ObArray<const char *> global_zone_item_names;
738if (!inited_) {
739ret = OB_NOT_INIT;
740LOG_WARN("not init", K(ret));
741} else if (OB_FAIL(check_cancel())) {
742LOG_WARN("check_cancel failed", K(ret));
743} else if (OB_FAIL(extra_cond.assign_fmt("zone = '%s'", global_zone_info.zone_.ptr()))) {
744LOG_WARN("extra_cond assign_fmt failed", K(ret));
745} else if (OB_FAIL(get_names(global_zone_info.list_, global_zone_item_names))) {
746LOG_WARN("get global zone item names failed", K(ret));
747} else if (OB_FAIL(check_names(OB_SYS_TENANT_ID, OB_ALL_ZONE_TNAME, global_zone_item_names, extra_cond))) {
748LOG_WARN("check global zone item names failed", "table_name", OB_ALL_ZONE_TNAME,
749K(global_zone_item_names), K(extra_cond), K(ret));
750} else if (OB_FAIL(zone_mgr_->get_zone(zone_infos))) {
751LOG_WARN("zone manager get_zone failed", K(ret));
752} else {
753ObArray<const char *> zone_item_names;
754FOREACH_CNT_X(zone_info, zone_infos, OB_SUCCESS == ret) {
755zone_item_names.reuse();
756extra_cond.reset();
757if (OB_FAIL(check_cancel())) {
758LOG_WARN("check_cancel failed", K(ret));
759} else if (OB_FAIL(extra_cond.assign_fmt("zone = '%s'", zone_info->zone_.ptr()))) {
760LOG_WARN("extra_cond assign_fmt failed", K(ret));
761} else if (OB_FAIL(get_names(zone_info->list_, zone_item_names))) {
762LOG_WARN("get zone item names failed", K(ret));
763} else if (OB_FAIL(check_names(OB_SYS_TENANT_ID, OB_ALL_ZONE_TNAME, zone_item_names, extra_cond))) {
764LOG_WARN("check zone item names failed", "table_name", OB_ALL_ZONE_TNAME,
765K(zone_item_names), "zone_info", *zone_info, K(extra_cond), K(ret));
766}
767}
768}
769}
770return ret;
771}
772
773int ObRootInspection::check_sys_stat_()
774{
775int ret = OB_SUCCESS;
776ObArray<uint64_t> tenant_ids;
777if (!inited_) {
778ret = OB_NOT_INIT;
779LOG_WARN("not init", KR(ret));
780} else if (OB_ISNULL(schema_service_)) {
781ret = OB_ERR_UNEXPECTED;
782LOG_WARN("schema_service is null", KR(ret));
783} else if (OB_FAIL(check_cancel())) {
784LOG_WARN("check_cancel failed", KR(ret));
785} else if (OB_FAIL(construct_tenant_ids_(tenant_ids))) {
786LOG_WARN("get_tenant_ids failed", KR(ret));
787} else {
788int backup_ret = OB_SUCCESS;
789int tmp_ret = OB_SUCCESS;
790FOREACH_CNT_X(tenant_id, tenant_ids, OB_SUCC(ret)) {
791if (OB_FAIL(check_cancel())) {
792LOG_WARN("check_cancel failed", KR(ret));
793} else if (OB_TMP_FAIL(check_sys_stat_(*tenant_id))) {
794LOG_WARN("fail to check sys stat", KR(tmp_ret), K(*tenant_id));
795backup_ret = OB_SUCCESS == backup_ret ? tmp_ret : backup_ret;
796}
797} // end foreach
798ret = OB_SUCC(ret) ? backup_ret : ret;
799}
800return ret;
801}
802
803int ObRootInspection::check_sys_stat_(const uint64_t tenant_id)
804{
805int ret = OB_SUCCESS;
806ObArray<const char *> sys_stat_names;
807ObSqlString extra_cond;
808ObSysStat sys_stat;
809const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
810if (!inited_) {
811ret = OB_NOT_INIT;
812LOG_WARN("not init", KR(ret));
813} else if (OB_ISNULL(schema_service_)) {
814ret = OB_ERR_UNEXPECTED;
815LOG_WARN("schema_service is null", KR(ret));
816} else if (OB_FAIL(check_cancel())) {
817LOG_WARN("check_cancel failed", KR(ret));
818} else if (OB_FAIL(check_tenant_status_(tenant_id))) {
819LOG_WARN("fail to check tenant status", KR(ret), K(tenant_id));
820} else if (OB_FAIL(sys_stat.set_initial_values(tenant_id))) {
821LOG_WARN("set initial values failed", KR(ret), K(tenant_id));
822} else if (OB_FAIL(extra_cond.assign_fmt("tenant_id = %lu",
823ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id)))) {
824LOG_WARN("extra_cond assign_fmt failed", KR(ret), K(tenant_id));
825} else if (OB_FAIL(get_names(sys_stat.item_list_, sys_stat_names))) {
826LOG_WARN("get sys stat names failed", KR(ret), K(tenant_id));
827} else if (OB_FAIL(check_names(tenant_id, OB_ALL_SYS_STAT_TNAME, sys_stat_names, extra_cond))) {
828LOG_WARN("check all sys stat names failed", K(ret), K(tenant_id),
829"table_name", OB_ALL_SYS_STAT_TNAME, K(sys_stat_names));
830}
831return ret;
832}
833
834int ObRootInspection::check_sys_param_()
835{
836int ret = OB_SUCCESS;
837ObArray<uint64_t> tenant_ids;
838if (!inited_) {
839ret = OB_NOT_INIT;
840LOG_WARN("not init", KR(ret));
841} else if (OB_ISNULL(schema_service_)) {
842ret = OB_ERR_UNEXPECTED;
843LOG_WARN("schema_service is null", KR(ret));
844} else if (OB_FAIL(check_cancel())) {
845LOG_WARN("check_cancel failed", KR(ret));
846} else if (OB_FAIL(construct_tenant_ids_(tenant_ids))) {
847LOG_WARN("get_tenant_ids failed", KR(ret));
848} else {
849int backup_ret = OB_SUCCESS;
850int tmp_ret = OB_SUCCESS;
851FOREACH_CNT_X(tenant_id, tenant_ids, OB_SUCC(ret)) {
852if (OB_FAIL(check_cancel())) {
853LOG_WARN("check_cancel failed", K(ret));
854} else if (OB_TMP_FAIL(check_sys_param_(*tenant_id))) {
855LOG_WARN("fail to check sys param", KR(tmp_ret), K(*tenant_id));
856backup_ret = OB_SUCCESS == backup_ret ? tmp_ret : backup_ret;
857}
858} // end foreach
859ret = OB_SUCC(ret) ? backup_ret : ret;
860}
861return ret;
862}
863
864int ObRootInspection::check_sys_param_(const uint64_t tenant_id)
865{
866int ret = OB_SUCCESS;
867ObArray<uint64_t> tenant_ids;
868ObArray<const char *> sys_param_names;
869ObSqlString extra_cond;
870const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
871if (!inited_) {
872ret = OB_NOT_INIT;
873LOG_WARN("not init", KR(ret));
874} else if (OB_ISNULL(schema_service_)) {
875ret = OB_ERR_UNEXPECTED;
876LOG_WARN("schema_service is null", KR(ret));
877} else if (OB_FAIL(check_cancel())) {
878LOG_WARN("check_cancel failed", KR(ret));
879} else if (OB_FAIL(check_tenant_status_(tenant_id))) {
880LOG_WARN("fail to check tenant status", KR(ret), K(tenant_id));
881} else if (OB_FAIL(extra_cond.assign_fmt("tenant_id = %lu",
882ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id)))) {
883LOG_WARN("extra_cond assign_fmt failed", KR(ret), K(tenant_id));
884} else if (OB_FAIL(get_sys_param_names(sys_param_names))) {
885LOG_WARN("get sys param names failed", KR(ret), K(tenant_id));
886} else if (OB_FAIL(check_names(tenant_id, OB_ALL_SYS_VARIABLE_TNAME,
887sys_param_names, extra_cond))) {
888LOG_WARN("check all sys params names failed", KR(ret), K(tenant_id),
889"table_name", OB_ALL_SYS_VARIABLE_TNAME, K(sys_param_names), K(extra_cond));
890}
891if (OB_SCHEMA_ERROR != ret) {
892} else if (GCONF.in_upgrade_mode()) {
893LOG_WARN("check sys_variable failed", KR(ret));
894} else {
895LOG_DBA_ERROR(OB_ERR_ROOT_INSPECTION, "msg", "system variables are unmatched", KR(ret));
896}
897return ret;
898}
899
900template<typename Item>
901int ObRootInspection::get_names(const ObDList<Item> &list, ObIArray<const char*> &names)
902{
903int ret = OB_SUCCESS;
904if (!inited_) {
905ret = OB_NOT_INIT;
906LOG_WARN("not init", K(ret));
907} else if (list.get_size() <= 0) {
908ret = OB_INVALID_ARGUMENT;
909LOG_WARN("list is empty", K(ret));
910} else {
911const Item *it = list.get_first();
912while (OB_SUCCESS == ret && it != list.get_header()) {
913if (OB_FAIL(names.push_back(it->name_))) {
914LOG_WARN("push_back failed", K(ret));
915} else {
916it = it->get_next();
917}
918}
919}
920return ret;
921}
922
923int ObRootInspection::get_sys_param_names(ObIArray<const char *> &names)
924{
925int ret = OB_SUCCESS;
926if (!inited_) {
927ret = OB_NOT_INIT;
928LOG_WARN("not init", K(ret));
929} else {
930const int64_t param_count = ObSysVariables::get_amount();
931for (int64_t i = 0; OB_SUCC(ret) && i < param_count; ++i) {
932if (OB_FAIL(names.push_back(ObSysVariables::get_name(i).ptr()))) {
933LOG_WARN("push_back failed", K(ret));
934}
935}
936}
937return ret;
938}
939
940int ObRootInspection::check_names(const uint64_t tenant_id,
941const char *table_name,
942const ObIArray<const char *> &names,
943const ObSqlString &extra_cond)
944{
945int ret = OB_SUCCESS;
946if (!inited_) {
947ret = OB_NOT_INIT;
948LOG_WARN("not init", K(ret));
949} else if (OB_FAIL(check_cancel())) {
950LOG_WARN("check_cancel failed", K(ret));
951} else if (NULL == table_name || names.count() <= 0) {
952// extra_cond can be empty, so wo don't check it here
953ret = OB_INVALID_ARGUMENT;
954LOG_WARN("table_name is null or names is empty", KP(table_name), K(names), K(ret));
955} else {
956ObArray<Name> fetch_names; // Get the data of the internal table
957ObArray<Name> extra_names; // data inner table more than hard code
958ObArray<Name> miss_names; // data inner table less than hard code
959if (OB_FAIL(calc_diff_names(tenant_id, table_name, names, extra_cond,
960fetch_names, extra_names, miss_names))) {
961LOG_WARN("fail to calc diff names", K(ret), KP(table_name), K(names), K(extra_cond));
962} else {
963if (fetch_names.count() <= 0) {
964// don't need to set ret
965LOG_WARN("maybe tenant or zone has been deleted, ignore it",
966K(tenant_id), K(table_name), K(extra_cond));
967} else {
968if (extra_names.count() > 0) {
969// don't need to set ret
970LOG_WARN("some item exist in table, but not hard coded",
971K(tenant_id), K(table_name), K(extra_names));
972}
973if (miss_names.count() > 0) {
974ret = OB_ENTRY_NOT_EXIST;
975LOG_WARN("some item exist in hard code, but not exist in inner table",
976K(ret), K(tenant_id), K(table_name), K(miss_names));
977}
978}
979}
980}
981return ret;
982}
983
984int ObRootInspection::calc_diff_names(const uint64_t tenant_id,
985const char *table_name,
986const ObIArray<const char *> &names,
987const ObSqlString &extra_cond,
988ObIArray<Name> &fetch_names, /* data reading from inner table*/
989ObIArray<Name> &extra_names, /* data inner table more than hard code*/
990ObIArray<Name> &miss_names /* data inner table less than hard code*/)
991{
992int ret = OB_SUCCESS;
993ObRefreshSchemaStatus schema_status;
994schema_status.tenant_id_ = tenant_id;
995fetch_names.reset();
996if (!inited_) {
997ret = OB_NOT_INIT;
998LOG_WARN("not init", K(ret));
999} else if (OB_INVALID_TENANT_ID == tenant_id) {
1000ret = OB_INVALID_ARGUMENT;
1001LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id));
1002} else if (OB_FAIL(check_cancel())) {
1003LOG_WARN("check_cancel failed", KR(ret), K(tenant_id));
1004} else if (NULL == table_name || names.count() <= 0) {
1005// extra_cond can be empty, don't need to check it
1006ret = OB_INVALID_ARGUMENT;
1007LOG_WARN("table_name is null or names is empty",
1008KR(ret), K(tenant_id), KP(table_name), K(names));
1009} else if (GCTX.is_standby_cluster() && is_user_tenant(tenant_id)) {
1010if (OB_ISNULL(GCTX.schema_status_proxy_)) {
1011ret = OB_ERR_UNEXPECTED;
1012LOG_WARN("schema status proxy is null", K(ret));
1013} else if (OB_FAIL(GCTX.schema_status_proxy_->get_refresh_schema_status(tenant_id, schema_status))) {
1014LOG_WARN("fail to get schema status", KR(ret), K(tenant_id));
1015}
1016}
1017
1018if (OB_SUCC(ret)) {
1019const uint64_t exec_tenant_id = schema_status.tenant_id_;
1020int64_t snapshot_timestamp = schema_status.snapshot_timestamp_;
1021ObSqlString sql;
1022ObSQLClientRetryWeak sql_client_retry_weak(sql_proxy_,
1023snapshot_timestamp);
1024if (OB_FAIL(sql.append_fmt("SELECT name FROM %s%s%s", table_name,
1025(extra_cond.empty()) ? "" : " WHERE ", extra_cond.ptr()))) {
1026LOG_WARN("append_fmt failed", KR(ret), K(tenant_id), K(table_name), K(extra_cond));
1027} else {
1028SMART_VAR(ObMySQLProxy::MySQLResult, res) {
1029ObMySQLResult *result = NULL;
1030if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) {
1031LOG_WARN("execute sql failed", KR(ret), K(tenant_id), K(sql));
1032can_retry_ = true;
1033} else if (OB_ISNULL(result = res.get_result())) {
1034ret = OB_ERR_UNEXPECTED;
1035LOG_WARN("result is not expected to be NULL",
1036KR(ret), K(tenant_id), "result", OB_P(result));
1037} else {
1038//only for filling the out parameter,
1039//Ensure that there is no '\ 0' character in the middle of the corresponding string
1040int64_t tmp_real_str_len = 0;
1041Name name;
1042while (OB_SUCC(ret)) {
1043if (OB_FAIL(result->next())) {
1044if (OB_ITER_END == ret) {
1045ret = OB_SUCCESS;
1046break;
1047} else {
1048LOG_WARN("get next result failed", KR(ret), K(tenant_id));
1049}
1050} else {
1051EXTRACT_STRBUF_FIELD_MYSQL(*result, "name", name.ptr(),
1052static_cast<int64_t>(NAME_BUF_LEN), tmp_real_str_len);
1053(void) tmp_real_str_len; // make compiler happy
1054if (OB_FAIL(fetch_names.push_back(name))) {
1055LOG_WARN("push_back failed", KR(ret), K(tenant_id));
1056}
1057}
1058}
1059}
1060}
1061}
1062if (OB_SUCC(ret)) {
1063if (fetch_names.count() <= 0) {
1064LOG_WARN("maybe tenant or zone has been deleted, ignore it",
1065KR(ret), K(schema_status), K(table_name), K(extra_cond));
1066} else {
1067extra_names.reset();
1068miss_names.reset();
1069FOREACH_CNT_X(fetch_name, fetch_names, OB_SUCCESS == ret) {
1070bool found = false;
1071FOREACH_CNT_X(name, names, OB_SUCC(ret)) {
1072if (Name(*name) == *fetch_name) {
1073found = true;
1074break;
1075}
1076}
1077if (!found) {
1078if (OB_FAIL(extra_names.push_back(*fetch_name))) {
1079LOG_WARN("fail to push name into fetch_names",
1080KR(ret), K(tenant_id), K(*fetch_name), K(fetch_names));
1081}
1082}
1083}
1084FOREACH_CNT_X(name, names, OB_SUCCESS == ret) {
1085bool found = false;
1086FOREACH_CNT_X(fetch_name, fetch_names, OB_SUCCESS == ret) {
1087if (Name(*name) == *fetch_name) {
1088found = true;
1089break;
1090}
1091}
1092if (!found) {
1093if (OB_FAIL(miss_names.push_back(Name(*name)))) {
1094LOG_WARN("fail to push name into miss_names",
1095KR(ret), K(tenant_id), K(*name), K(miss_names));
1096}
1097}
1098}
1099}
1100}
1101}
1102return ret;
1103}
1104
1105int ObRootInspection::check_sys_table_schemas_()
1106{
1107int ret = OB_SUCCESS;
1108ObArray<uint64_t> tenant_ids;
1109if (OB_UNLIKELY(!inited_)) {
1110ret = OB_NOT_INIT;
1111LOG_WARN("not init", KR(ret));
1112} else if (OB_FAIL(check_cancel())) {
1113LOG_WARN("check_cancel failed", KR(ret));
1114} else if (OB_ISNULL(schema_service_)) {
1115ret = OB_ERR_UNEXPECTED;
1116LOG_WARN("schema_service is null", KR(ret));
1117} else if (OB_FAIL(construct_tenant_ids_(tenant_ids))) {
1118LOG_WARN("get_tenant_ids failed", KR(ret));
1119} else {
1120int backup_ret = OB_SUCCESS;
1121int tmp_ret = OB_SUCCESS;
1122FOREACH_X(tenant_id, tenant_ids, OB_SUCC(ret)) {
1123if (OB_FAIL(check_cancel())) {
1124LOG_WARN("check_cancel failed", KR(ret));
1125} else if (OB_TMP_FAIL(check_sys_table_schemas_(*tenant_id))) {
1126LOG_WARN("fail to check sys table schemas by tenant", KR(tmp_ret), K(*tenant_id));
1127backup_ret = OB_SUCCESS == backup_ret ? tmp_ret : backup_ret;
1128}
1129} // end foreach
1130ret = OB_SUCC(ret) ? backup_ret : ret;
1131}
1132return ret;
1133}
1134
1135int ObRootInspection::check_sys_table_schemas_(
1136const uint64_t tenant_id)
1137{
1138int ret = OB_SUCCESS;
1139int64_t schema_version = OB_INVALID_VERSION;
1140if (OB_UNLIKELY(!inited_)) {
1141ret = OB_NOT_INIT;
1142LOG_WARN("not init", KR(ret));
1143} else if (OB_FAIL(check_cancel())) {
1144LOG_WARN("check_cancel failed", KR(ret));
1145} else if (OB_UNLIKELY(
1146is_virtual_tenant_id(tenant_id)
1147|| OB_INVALID_TENANT_ID == tenant_id)) {
1148ret = OB_INVALID_ARGUMENT;
1149LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id));
1150} else {
1151const schema_create_func *creator_ptr_array[] = {
1152share::all_core_table_schema_creator,
1153share::core_table_schema_creators,
1154share::sys_table_schema_creators,
1155share::virtual_table_schema_creators,
1156share::sys_view_schema_creators,
1157share::core_index_table_schema_creators,
1158share::sys_index_table_schema_creators,
1159NULL };
1160
1161int back_ret = OB_SUCCESS;
1162int tmp_ret = OB_SUCCESS;
1163ObTableSchema table_schema;
1164bool exist = false;
1165for (const schema_create_func **creator_ptr_ptr = creator_ptr_array;
1166OB_SUCC(ret) && OB_NOT_NULL(*creator_ptr_ptr); ++creator_ptr_ptr) {
1167for (const schema_create_func *creator_ptr = *creator_ptr_ptr;
1168OB_SUCC(ret) && OB_NOT_NULL(*creator_ptr); ++creator_ptr) {
1169table_schema.reset();
1170if (OB_FAIL(check_cancel())) {
1171LOG_WARN("check_cancel failed", KR(ret));
1172} else if (OB_FAIL(check_tenant_status_(tenant_id))) {
1173LOG_WARN("fail to check tenant status", KR(ret), K(tenant_id));
1174} else if (OB_FAIL((*creator_ptr)(table_schema))) {
1175LOG_WARN("create table schema failed", KR(ret));
1176} else if (!is_sys_tenant(tenant_id)
1177&& OB_FAIL(ObSchemaUtils::construct_tenant_space_full_table(
1178tenant_id, table_schema))) {
1179LOG_WARN("fail to construct tenant space table", KR(ret), K(tenant_id));
1180} else if (OB_FAIL(ObSysTableChecker::is_inner_table_exist(
1181tenant_id, table_schema, exist))) {
1182LOG_WARN("fail to check inner table exist",
1183KR(ret), K(tenant_id), K(table_schema));
1184} else if (!exist) {
1185// skip
1186} else {
1187if (OB_TMP_FAIL(check_table_schema(tenant_id, table_schema))) {
1188// don't print table_schema, otherwise log will be too much
1189LOG_WARN("check table schema failed", KR(tmp_ret), K(tenant_id),
1190"table_id", table_schema.get_table_id(), "table_name", table_schema.get_table_name());
1191back_ret = OB_SUCCESS == back_ret ? tmp_ret : back_ret;
1192}
1193
1194if (OB_TMP_FAIL(check_sys_view_(tenant_id, table_schema))) {
1195LOG_WARN("check sys view failed", KR(tmp_ret), K(tenant_id),
1196"table_id", table_schema.get_table_id(), "table_name", table_schema.get_table_name());
1197back_ret = OB_SUCCESS == back_ret ? tmp_ret : back_ret;
1198// sql may has occur other error except OB_SCHEMA_ERROR, we should not continue is such situation.
1199if (OB_SCHEMA_ERROR != tmp_ret) {
1200ret = OB_SUCC(ret) ? back_ret : tmp_ret;
1201}
1202}
1203}
1204} // end for
1205} // end for
1206ret = OB_SUCC(ret) ? back_ret : ret;
1207}
1208if (OB_SCHEMA_ERROR != ret) {
1209} else if (GCONF.in_upgrade_mode()) {
1210LOG_WARN("check sys table schema failed", KR(ret), K(tenant_id));
1211} else {
1212LOG_ERROR("check sys table schema failed", KR(ret), K(tenant_id));
1213LOG_DBA_ERROR(OB_ERR_ROOT_INSPECTION, "msg", "inner tables are unmatched", KR(ret), K(tenant_id));
1214}
1215return ret;
1216}
1217
1218int ObRootInspection::check_table_schema(
1219const uint64_t tenant_id,
1220const ObTableSchema &hard_code_table)
1221{
1222int ret = OB_SUCCESS;
1223const ObTableSchema *table = NULL;
1224ObSchemaGetterGuard schema_guard;
1225if (OB_UNLIKELY(!inited_)) {
1226ret = OB_NOT_INIT;
1227LOG_WARN("not init", KR(ret));
1228} else if (OB_UNLIKELY(
1229is_virtual_tenant_id(tenant_id)
1230|| OB_INVALID_TENANT_ID == tenant_id)) {
1231ret = OB_INVALID_ARGUMENT;
1232LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id));
1233} else if (OB_UNLIKELY(!hard_code_table.is_valid())) {
1234ret = OB_INVALID_ARGUMENT;
1235LOG_WARN("invalid table_schema", KR(ret), K(tenant_id), K(hard_code_table));
1236} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
1237LOG_WARN("failed to get schema guard", KR(ret), K(tenant_id));
1238} else if (OB_FAIL(schema_guard.get_table_schema(
1239tenant_id, hard_code_table.get_table_id(), table))) {
1240LOG_WARN("get_table_schema failed", KR(ret), K(tenant_id),
1241"table_id", hard_code_table.get_table_id(),
1242"table_name", hard_code_table.get_table_name());
1243// fail may cause by load table schema sql, set retry flag.
1244can_retry_ = true;
1245} else if (OB_ISNULL(table)) {
1246ret = OB_SCHEMA_ERROR;
1247LOG_WARN("table should not be null", KR(ret), K(tenant_id),
1248"table_id", hard_code_table.get_table_id(),
1249"table_name", hard_code_table.get_table_name());
1250can_retry_ = true;
1251} else if (OB_FAIL(check_table_schema(hard_code_table, *table))) {
1252LOG_WARN("fail to check table schema", KR(ret), K(tenant_id), K(hard_code_table), KPC(table));
1253}
1254return ret;
1255}
1256
1257int ObRootInspection::check_table_schema(const ObTableSchema &hard_code_table,
1258const ObTableSchema &inner_table)
1259{
1260int ret = OB_SUCCESS;
1261if (!hard_code_table.is_valid()
1262|| !inner_table.is_valid()) {
1263ret = OB_INVALID_ARGUMENT;
1264LOG_WARN("invalid table_schema", K(hard_code_table), K(inner_table), K(ret));
1265} else if (OB_FAIL(check_table_options_(inner_table, hard_code_table))) {
1266LOG_WARN("check_table_options failed", "table_id", hard_code_table.get_table_id(), K(ret));
1267} else if (!inner_table.is_view_table()) { //view table do not check column info
1268if (hard_code_table.get_column_count() != inner_table.get_column_count()) {
1269ret = OB_SCHEMA_ERROR;
1270LOG_WARN("column count mismatch", "table_id", inner_table.get_table_id(),
1271"table_name",inner_table.get_table_name(), "table_column_cnt",inner_table.get_column_count(),
1272"hard_code_table_column_cnt", hard_code_table.get_column_count(), K(ret));
1273} else {
1274int back_ret = OB_SUCCESS;
1275for (int64_t i = 0; OB_SUCC(ret) && i < hard_code_table.get_column_count(); ++i) {
1276const ObColumnSchemaV2 *hard_code_column = hard_code_table.get_column_schema_by_idx(i);
1277const ObColumnSchemaV2 *column = NULL;
1278if (NULL == hard_code_column) {
1279ret = OB_SCHEMA_ERROR;
1280LOG_WARN("hard_code_column is null", "hard_code_column", OB_P(hard_code_column), K(ret));
1281} else if (NULL == (column = inner_table.get_column_schema(
1282hard_code_column->get_column_name()))) {
1283ret = OB_SCHEMA_ERROR;
1284LOG_WARN("hard code column not found", "table_id", hard_code_table.get_table_id(),
1285"table_name", hard_code_table.get_table_name(), "column",
1286hard_code_column->get_column_name(), K(ret));
1287} else {
1288const bool ignore_column_id = is_virtual_table(hard_code_table.get_table_id());
1289if (OB_FAIL(check_column_schema_(hard_code_table.get_table_name(),
1290*column, *hard_code_column, ignore_column_id))) {
1291LOG_WARN("column schema mismatch with hard code column schema",
1292"table_name",inner_table.get_table_name(), "column", *column,
1293"hard_code_column", *hard_code_column, K(ret));
1294}
1295}
1296back_ret = OB_SUCCESS == back_ret ? ret : back_ret;
1297ret = OB_SUCCESS;
1298}
1299ret = back_ret;
1300}
1301}
1302return ret;
1303}
1304
1305int ObRootInspection::check_and_get_system_table_column_diff(
1306const share::schema::ObTableSchema &table_schema,
1307const share::schema::ObTableSchema &hard_code_schema,
1308common::ObIArray<uint64_t> &add_column_ids,
1309common::ObIArray<uint64_t> &alter_column_ids)
1310{
1311int ret = OB_SUCCESS;
1312add_column_ids.reset();
1313alter_column_ids.reset();
1314if (!table_schema.is_valid() || !hard_code_schema.is_valid()) {
1315ret = OB_INVALID_ARGUMENT;
1316LOG_WARN("invalid table_schema", KR(ret), K(table_schema), K(hard_code_schema));
1317} else if (table_schema.get_tenant_id() != hard_code_schema.get_tenant_id()
1318|| table_schema.get_table_id() != hard_code_schema.get_table_id()
1319|| 0 != table_schema.get_table_name_str().compare(hard_code_schema.get_table_name_str())
1320|| !is_system_table(table_schema.get_table_id())) {
1321ret = OB_INVALID_ARGUMENT;
1322LOG_WARN("invalid table_schema", KR(ret),
1323"tenant_id", table_schema.get_tenant_id(),
1324"table_id", table_schema.get_table_id(),
1325"table_name", table_schema.get_table_name(),
1326"hard_code_tenant_id", hard_code_schema.get_tenant_id(),
1327"hard_code_table_id", hard_code_schema.get_table_id(),
1328"hard_code_table_name", hard_code_schema.get_table_name());
1329} else {
1330const uint64_t tenant_id = table_schema.get_tenant_id();
1331const uint64_t table_id = table_schema.get_table_id();
1332const ObColumnSchemaV2 *column = NULL;
1333const ObColumnSchemaV2 *hard_code_column = NULL;
1334ObColumnSchemaV2 tmp_column; // check_column_can_be_altered_online() may change dst_column, is ugly.
1335bool ignore_column_id = false;
1336
1337// case 1. check if columns should be dropped.
1338// case 2. check if column can be altered online.
1339for (int64_t i = 0; OB_SUCC(ret) && i < table_schema.get_column_count(); i++) {
1340column = table_schema.get_column_schema_by_idx(i);
1341if (OB_ISNULL(column)) {
1342ret = OB_ERR_UNEXPECTED;
1343LOG_WARN("column schema is null", KR(ret), K(tenant_id), K(table_id), K(i));
1344} else if (OB_ISNULL(hard_code_column = hard_code_schema.get_column_schema(column->get_column_id()))) {
1345ret = OB_NOT_SUPPORTED; // case 1
1346LOG_WARN("can't drop system table's column", KR(ret),
1347K(tenant_id), K(table_id),
1348"table_name", table_schema.get_table_name(),
1349"column_id", column->get_column_id(),
1350"column_name", column->get_column_name());
1351} else {
1352// case 2
1353int tmp_ret = check_column_schema_(table_schema.get_table_name_str(),
1354*column,
1355*hard_code_column,
1356ignore_column_id);
1357if (OB_SUCCESS == tmp_ret) {
1358// not changed
1359} else if (OB_SCHEMA_ERROR != tmp_ret) {
1360ret = tmp_ret;
1361LOG_WARN("fail to check column schema", KR(ret),
1362K(tenant_id), K(table_id), KPC(column), KPC(hard_code_column));
1363} else if (OB_FAIL(tmp_column.assign(*hard_code_column))) {
1364LOG_WARN("fail to assign hard code column schema", KR(ret),
1365K(tenant_id), K(table_id), "column_id", hard_code_column->get_column_id());
1366} else if (OB_FAIL(table_schema.check_column_can_be_altered_online(column, &tmp_column))) {
1367LOG_WARN("fail to check alter column online", KR(ret),
1368K(tenant_id), K(table_id),
1369"table_name", table_schema.get_table_name(),
1370"column_id", column->get_column_id(),
1371"column_name", column->get_column_name());
1372} else if (OB_FAIL(alter_column_ids.push_back(column->get_column_id()))) {
1373LOG_WARN("fail to push back column_id", KR(ret), K(tenant_id), K(table_id),
1374"column_id", column->get_column_id());
1375}
1376}
1377} // end for
1378
1379// case 3: check if columns should be added.
1380for (int64_t i = 0; OB_SUCC(ret) && i < hard_code_schema.get_column_count(); i++) {
1381hard_code_column = hard_code_schema.get_column_schema_by_idx(i);
1382if (OB_ISNULL(hard_code_column)) {
1383ret = OB_ERR_UNEXPECTED;
1384LOG_WARN("column schema is null", KR(ret), K(tenant_id), K(table_id), K(i));
1385} else if (OB_NOT_NULL(column = table_schema.get_column_schema(hard_code_column->get_column_id()))) {
1386// column exist, just skip
1387} else {
1388const uint64_t hard_code_column_id = hard_code_column->get_column_id();
1389const ObColumnSchemaV2 *last_column = NULL;
1390if (table_schema.get_column_count() <= 0
1391|| OB_ISNULL(last_column = table_schema.get_column_schema_by_idx(
1392table_schema.get_column_count() - 1))) {
1393ret = OB_ERR_UNEXPECTED;
1394LOG_WARN("invalid column count or column", KR(ret), K(table_schema));
1395} else if (table_schema.get_max_used_column_id() >= hard_code_column_id
1396|| last_column->get_column_id() >= hard_code_column_id) {
1397ret = OB_NOT_SUPPORTED;
1398LOG_WARN("column should be added at last", KR(ret), KPC(hard_code_column), K(table_schema));
1399} else if (OB_FAIL(add_column_ids.push_back(hard_code_column_id))) {
1400LOG_WARN("fail to push back column_id", KR(ret), K(tenant_id), K(table_id),
1401"column_id", hard_code_column_id);
1402}
1403}
1404} // end for
1405}
1406return ret;
1407}
1408
1409bool ObRootInspection::check_str_with_lower_case_(const ObString &str)
1410{
1411bool bret = false;
1412if (str.length() > 0) {
1413for (int64_t i = 0; !bret && i < str.length(); i++) {
1414if (str.ptr()[i] >= 'a' && str.ptr()[i] <= 'z') {
1415bret = true;
1416}
1417}
1418}
1419return bret;
1420}
1421
1422int ObRootInspection::check_sys_view_(
1423const uint64_t tenant_id,
1424const ObTableSchema &hard_code_table)
1425{
1426int ret = OB_SUCCESS;
1427if (OB_ISNULL(GCTX.root_service_)) {
1428ret = OB_NOT_INIT;
1429LOG_WARN("not init", KR(ret));
1430} else if (hard_code_table.is_view_table()) {
1431// check view definition
1432const ObString &table_name = hard_code_table.get_table_name();
1433const uint64_t table_id = hard_code_table.get_table_id();
1434const uint64_t database_id = hard_code_table.get_database_id();
1435bool is_oracle = is_oracle_sys_database_id(database_id);
1436bool check_lower_case = !is_mysql_database_id(database_id);
1437SMART_VAR(ObMySQLProxy::MySQLResult, res) {
1438common::sqlclient::ObMySQLResult *result = NULL;
1439ObSqlString sql;
1440// case 0: check expansion of sys view definition
1441if (is_oracle) {
1442if (OB_FAIL(sql.assign_fmt("SELECT FIELD FROM \"%s\".\"%s\" WHERE TABLE_ID = %lu",
1443OB_ORA_SYS_SCHEMA_NAME,
1444OB_TENANT_VIRTUAL_TABLE_COLUMN_ORA_TNAME,
1445table_id))) {
1446LOG_WARN("failed to assign sql", KR(ret), K(sql));
1447} else if (OB_FAIL(GCTX.root_service_->get_oracle_sql_proxy().read(res, tenant_id, sql.ptr()))) {
1448LOG_WARN("execute sql failed", KR(ret), K(tenant_id), K(table_name), K(sql));
1449}
1450} else {
1451if (OB_FAIL(sql.assign_fmt("SELECT FIELD FROM `%s`.`%s` WHERE TABLE_ID = %lu",
1452OB_SYS_DATABASE_NAME,
1453OB_TENANT_VIRTUAL_TABLE_COLUMN_TNAME,
1454table_id))) {
1455LOG_WARN("failed to assign sql", KR(ret), K(sql));
1456} else if (!is_oracle && OB_FAIL(GCTX.root_service_->get_sql_proxy().read(res, tenant_id, sql.ptr()))) {
1457LOG_WARN("execute sql failed", KR(ret), K(tenant_id), K(table_name), K(sql));
1458}
1459}
1460if (OB_FAIL(ret)) {
1461if (OB_ERR_VIEW_INVALID == ret) {
1462ret = OB_SCHEMA_ERROR;
1463LOG_ERROR("check sys view: expand failed", KR(ret), K(tenant_id), K(table_name));
1464} else {
1465LOG_WARN("check sys view: expand failed", KR(ret), K(tenant_id), K(table_name));
1466}
1467} else if (OB_ISNULL(result = res.get_result())) {
1468ret = OB_ERR_UNEXPECTED;
1469LOG_WARN("failed to get sql result", KR(ret), K(tenant_id));
1470} else if (check_lower_case) {
1471// case 1: check column name with lower case
1472ObString col_name;
1473while (OB_SUCC(ret) && OB_SUCC(result->next())) {
1474if (OB_FAIL(result->get_varchar(0L, col_name))) {
1475LOG_WARN("fail to get filed", KR(ret), K(tenant_id), K(table_name));
1476} else if (check_str_with_lower_case_(col_name)) {
1477ret = OB_SCHEMA_ERROR;
1478LOG_ERROR("check sys view: column name should be uppercase",
1479KR(ret), K(tenant_id), K(table_name), K(col_name));
1480}
1481} // end while
1482if (OB_ITER_END == ret) {
1483ret = OB_SUCCESS;
1484} else {
1485ret = OB_SUCC(ret) ? OB_ERR_UNEXPECTED : ret;
1486LOG_WARN("iterate failed", KR(ret));
1487}
1488// case 2: check view name with lower case
1489if (OB_SUCC(ret) && check_str_with_lower_case_(hard_code_table.get_table_name())) {
1490ret = OB_SCHEMA_ERROR;
1491LOG_ERROR("check sys view: table name should be uppercase", KR(ret), K(tenant_id), K(table_name));
1492}
1493}
1494}
1495}
1496return ret;
1497}
1498
1499int ObRootInspection::check_table_options_(const ObTableSchema &table,
1500const ObTableSchema &hard_code_table)
1501{
1502int ret = OB_SUCCESS;
1503if (!table.is_valid() || !hard_code_table.is_valid()) {
1504ret = OB_INVALID_ARGUMENT;
1505LOG_WARN("invalid table or invalid hard_code_table", K(table), K(hard_code_table), K(ret));
1506} else if (table.get_table_id() != hard_code_table.get_table_id()) {
1507ret = OB_SCHEMA_ERROR;
1508LOG_WARN("table id not match", "table_id", table.get_table_id(),
1509"hard_code table_id", hard_code_table.get_table_id(), K(ret));
1510} else if (table.get_table_name_str() != hard_code_table.get_table_name_str()) {
1511ret = OB_SCHEMA_ERROR;
1512LOG_WARN("table name mismatch with hard code table",
1513"table_id", table.get_table_id(), "table_name", table.get_table_name(),
1514"hard_code_table name", hard_code_table.get_table_name(), K(ret));
1515} else {
1516const ObString &table_name = table.get_table_name_str();
1517
1518if (table.get_tenant_id() != hard_code_table.get_tenant_id()) {
1519ret = OB_SCHEMA_ERROR;
1520LOG_WARN("tenant_id mismatch", K(table_name), "in_memory", table.get_tenant_id(),
1521"hard_code", hard_code_table.get_tenant_id(), K(ret));
1522} else if (table.get_database_id() != hard_code_table.get_database_id()) {
1523ret = OB_SCHEMA_ERROR;
1524LOG_WARN("database_id mismatch", K(table_name), "in_memory", table.get_database_id(),
1525"hard_code", hard_code_table.get_database_id(), K(ret));
1526} else if (table.get_tablegroup_id() != hard_code_table.get_tablegroup_id()) {
1527ret = OB_SCHEMA_ERROR;
1528LOG_WARN("tablegroup_id mismatch", K(table_name), "in_memory", table.get_tablegroup_id(),
1529"hard_code", hard_code_table.get_tablegroup_id(), K(ret));
1530} else if (table.get_auto_increment() != hard_code_table.get_auto_increment()) {
1531ret = OB_SCHEMA_ERROR;
1532LOG_WARN("auto_increment mismatch", K(table_name), "in_memory", table.get_auto_increment(),
1533"hard_code", hard_code_table.get_auto_increment(), K(ret));
1534} else if (table.is_read_only() != hard_code_table.is_read_only()) {
1535ret = OB_SCHEMA_ERROR;
1536LOG_WARN("read_only mismatch", K(table_name), "in_memory", table.is_read_only(),
1537"hard code", hard_code_table.is_read_only(), K(ret));
1538} else if (table.get_load_type() != hard_code_table.get_load_type()) {
1539ret = OB_SCHEMA_ERROR;
1540LOG_WARN("load_type mismatch", K(table_name), "in_memory", table.get_load_type(),
1541"hard_code", hard_code_table.get_load_type(), K(ret));
1542} else if (table.get_table_type() != hard_code_table.get_table_type()) {
1543ret = OB_SCHEMA_ERROR;
1544LOG_WARN("table_type mismatch", K(table_name), "in_memory", table.get_table_type(),
1545"hard_code", hard_code_table.get_table_type(), K(ret));
1546} else if (table.get_index_type() != hard_code_table.get_index_type()) {
1547ret = OB_SCHEMA_ERROR;
1548LOG_WARN("index_type mismatch", K(table_name), "in_memory", table.get_index_type(),
1549"hard_code", hard_code_table.get_index_type(), K(ret));
1550} else if (table.get_index_using_type() != hard_code_table.get_index_using_type()) {
1551ret = OB_SCHEMA_ERROR;
1552LOG_WARN("index_using_type mismatch", K(table_name), "in_memory", table.get_index_using_type(),
1553"hard_code", hard_code_table.get_index_using_type(), K(ret));
1554} else if (table.get_def_type() != hard_code_table.get_def_type()) {
1555ret = OB_SCHEMA_ERROR;
1556LOG_WARN("def_type mismatch", K(table_name), "in_memory", table.get_def_type(),
1557"hard_code", hard_code_table.get_def_type(), K(ret));
1558} else if (table.get_data_table_id() != hard_code_table.get_data_table_id()) {
1559ret = OB_SCHEMA_ERROR;
1560LOG_WARN("data_table_id mismatch", K(table_name), "in_memory", table.get_data_table_id(),
1561"hard_code", hard_code_table.get_data_table_id(), K(ret));
1562} else if (table.get_tablegroup_name() != hard_code_table.get_tablegroup_name()) {
1563ret = OB_SCHEMA_ERROR;
1564LOG_WARN("tablegroup_name mismatch", K(table_name), "in_memory", table.get_tablegroup_name(),
1565"hard_code", hard_code_table.get_tablegroup_name(), K(ret));
1566} else if (table.get_view_schema() != hard_code_table.get_view_schema()) {
1567ret = OB_SCHEMA_ERROR;
1568LOG_WARN("view_schema mismatch", K(table_name), "in_memory", table.get_view_schema(),
1569"hard_code", hard_code_table.get_view_schema(), K(ret));
1570} else if (table.get_part_level() != hard_code_table.get_part_level()) {
1571ret = OB_SCHEMA_ERROR;
1572LOG_WARN("part_level mismatch", K(table_name), "in_memory", table.get_part_level(),
1573"hard_code", hard_code_table.get_part_level(), K(ret));
1574} else if ((table.get_part_option().get_part_func_expr_str()
1575!= hard_code_table.get_part_option().get_part_func_expr_str())
1576|| (table.get_part_option().get_part_func_type()
1577!= hard_code_table.get_part_option().get_part_func_type())) {
1578ret = OB_SCHEMA_ERROR;
1579LOG_WARN("part_expr mismatch", K(table_name), "in_memory",
1580table.get_part_option(), "hard_code", hard_code_table.get_part_option(), K(ret));
1581} else if ((table.get_sub_part_option().get_part_func_expr_str()
1582!= hard_code_table.get_sub_part_option().get_part_func_expr_str())
1583|| (table.get_sub_part_option().get_part_func_type()
1584!= hard_code_table.get_sub_part_option().get_part_func_type())) {
1585ret = OB_SCHEMA_ERROR;
1586LOG_WARN("sub_part_expr mismatch", K(table_name), "in_memory",
1587table.get_sub_part_option(), "hard_code", hard_code_table.get_sub_part_option(), K(ret));
1588} else if (table.is_view_table()) {
1589// view table do not check column info
1590} else if (table.get_max_used_column_id() < hard_code_table.get_max_used_column_id()) {
1591ret = OB_SCHEMA_ERROR;
1592LOG_WARN("max_used_column_id mismatch", K(table_name), "in_memory",
1593table.get_max_used_column_id(), "hard_code",
1594hard_code_table.get_max_used_column_id(), K(ret));
1595} else if (table.get_rowkey_column_num() != hard_code_table.get_rowkey_column_num()) {
1596ret = OB_SCHEMA_ERROR;
1597LOG_WARN("rowkey_column_num mismatch", K(table_name), "in_memory",
1598table.get_rowkey_column_num(), "hard_code",
1599hard_code_table.get_rowkey_column_num(), K(ret));
1600} else if (table.get_index_column_num() != hard_code_table.get_index_column_num()) {
1601ret = OB_SCHEMA_ERROR;
1602LOG_WARN("index_column_num mismatch", K(table_name), "in_memory",
1603table.get_index_column_num(), "hard_code",
1604hard_code_table.get_index_column_num(), K(ret));
1605} else if (table.get_rowkey_split_pos() != hard_code_table.get_rowkey_split_pos()) {
1606ret = OB_SCHEMA_ERROR;
1607LOG_WARN("rowkey_split_pos mismatch", K(table_name), "in_memory",
1608table.get_rowkey_split_pos(), "hard_code",
1609hard_code_table.get_rowkey_split_pos(), K(ret));
1610} else if (table.get_partition_key_column_num()
1611!= hard_code_table.get_partition_key_column_num()) {
1612ret = OB_SCHEMA_ERROR;
1613LOG_WARN("partition_key_column_num mismatch", K(table_name), "in_memory",
1614table.get_partition_key_column_num(), "hard_code",
1615hard_code_table.get_partition_key_column_num(), K(ret));
1616} else if (table.get_subpartition_key_column_num()
1617!= hard_code_table.get_subpartition_key_column_num()) {
1618ret = OB_SCHEMA_ERROR;
1619LOG_WARN("partition_key_column_num mismatch", K(table_name), "in_memory",
1620table.get_subpartition_key_column_num(), "hard_code",
1621hard_code_table.get_subpartition_key_column_num(), K(ret));
1622} else if (table.get_autoinc_column_id() != hard_code_table.get_autoinc_column_id()) {
1623ret = OB_SCHEMA_ERROR;
1624LOG_WARN("autoinc_column_id mismatch", K(table_name), "in_memory",
1625table.get_autoinc_column_id(), "hard_code",
1626hard_code_table.get_autoinc_column_id(), K(ret));
1627}
1628
1629// options may be different between different ob instance, don't check
1630// block_size
1631// is_user_bloomfilter
1632// progressive_merge_num
1633// replica_num
1634// index_status
1635// name_case_mode
1636// charset_type
1637// collation_type
1638// schema_version
1639// comment
1640// compress_func_name
1641// expire_info
1642// zone_list
1643// primary_zone
1644// part_expr.part_num_
1645// sub_part_expr.part_num_
1646// store_format
1647// row_store_type
1648// progressive_merge_round
1649// storage_format_version
1650}
1651return ret;
1652}
1653
1654int ObRootInspection::check_column_schema_(const ObString &table_name,
1655const ObColumnSchemaV2 &column,
1656const ObColumnSchemaV2 &hard_code_column,
1657const bool ignore_column_id)
1658{
1659int ret = OB_SUCCESS;
1660if (table_name.empty() || !column.is_valid() || !hard_code_column.is_valid()) {
1661ret = OB_INVALID_ARGUMENT;
1662LOG_WARN("table_name is empty or invalid column or invalid hard_code_column",
1663KR(ret), K(table_name), K(column), K(hard_code_column));
1664} else {
1665#define CMP_COLUMN_ATTR(attr) \
1666if (OB_SUCC(ret)) { \
1667if (column.get_##attr() != hard_code_column.get_##attr()) { \
1668ret = OB_SCHEMA_ERROR; \
1669LOG_WARN(#attr " mismatch", KR(ret), K(table_name), "column_name", column.get_column_name(), \
1670"in_memory", column.get_##attr(), "hard_code", hard_code_column.get_##attr()); \
1671} \
1672}
1673
1674#define CMP_COLUMN_IS_ATTR(attr) \
1675if (OB_SUCC(ret)) { \
1676if (column.is_##attr() != hard_code_column.is_##attr()) { \
1677ret = OB_SCHEMA_ERROR; \
1678LOG_WARN(#attr " mismatch", KR(ret), K(table_name), "column_name", column.get_column_name(), \
1679"in_memory", column.is_##attr(), "hard_code", hard_code_column.is_##attr()); \
1680} \
1681}
1682if (OB_SUCC(ret)) {
1683if (column.get_column_name_str() != hard_code_column.get_column_name_str()) {
1684ret = OB_SCHEMA_ERROR;
1685LOG_WARN("column_name mismatch", KR(ret), K(table_name),
1686"in_memory", column.get_column_name(),
1687"hard_code", hard_code_column.get_column_name());
1688}
1689}
1690
1691if (!ignore_column_id) {
1692CMP_COLUMN_ATTR(column_id);
1693}
1694CMP_COLUMN_ATTR(tenant_id);
1695CMP_COLUMN_ATTR(table_id);
1696// don't need to check schema version
1697CMP_COLUMN_ATTR(rowkey_position);
1698CMP_COLUMN_ATTR(index_position);
1699CMP_COLUMN_ATTR(order_in_rowkey);
1700CMP_COLUMN_ATTR(tbl_part_key_pos);
1701CMP_COLUMN_ATTR(meta_type);
1702CMP_COLUMN_ATTR(accuracy);
1703CMP_COLUMN_ATTR(data_length);
1704CMP_COLUMN_IS_ATTR(nullable);
1705CMP_COLUMN_IS_ATTR(zero_fill);
1706CMP_COLUMN_IS_ATTR(autoincrement);
1707CMP_COLUMN_IS_ATTR(hidden);
1708CMP_COLUMN_IS_ATTR(on_update_current_timestamp);
1709CMP_COLUMN_ATTR(charset_type);
1710// don't need to check orig default value
1711if (ObString("row_store_type") == column.get_column_name()
1712&& (ObString("__all_table") == table_name || ObString("__all_table_history") == table_name)) {
1713// row_store_type may have two possible default values
1714} else {
1715CMP_COLUMN_ATTR(cur_default_value);
1716}
1717CMP_COLUMN_ATTR(comment);
1718
1719}
1720
1721#undef CMP_COLUMN_IS_ATTR
1722#undef CMP_COLUMN_INT_ATTR
1723return ret;
1724}
1725
1726int ObRootInspection::check_data_version_()
1727{
1728int ret = OB_SUCCESS;
1729ObArray<uint64_t> tenant_ids;
1730if (OB_UNLIKELY(!inited_)) {
1731ret = OB_NOT_INIT;
1732LOG_WARN("not init", KR(ret));
1733} else if (OB_FAIL(check_cancel())) {
1734LOG_WARN("check_cancel failed", KR(ret));
1735} else if (OB_ISNULL(schema_service_)) {
1736ret = OB_ERR_UNEXPECTED;
1737LOG_WARN("schema_service is null", KR(ret));
1738} else if (OB_FAIL(construct_tenant_ids_(tenant_ids))) {
1739LOG_WARN("get_tenant_ids failed", KR(ret));
1740} else {
1741int backup_ret = OB_SUCCESS;
1742int tmp_ret = OB_SUCCESS;
1743FOREACH_X(tenant_id, tenant_ids, OB_SUCC(ret)) {
1744if (OB_FAIL(check_cancel())) {
1745LOG_WARN("check_cancel failed", KR(ret));
1746} else if (OB_FAIL(check_tenant_status_(*tenant_id))) {
1747LOG_WARN("fail to check tenant status", KR(ret), K(*tenant_id));
1748} else if (OB_TMP_FAIL(check_data_version_(*tenant_id))) {
1749LOG_WARN("fail to check data version by tenant", KR(tmp_ret), K(*tenant_id));
1750backup_ret = OB_SUCCESS == backup_ret ? tmp_ret : backup_ret;
1751}
1752} // end foreach
1753ret = OB_SUCC(ret) ? backup_ret : ret;
1754}
1755return ret;
1756}
1757
1758int ObRootInspection::check_data_version_(
1759const uint64_t tenant_id)
1760{
1761int ret = OB_SUCCESS;
1762if (OB_UNLIKELY(!inited_)) {
1763ret = OB_NOT_INIT;
1764LOG_WARN("not init", KR(ret));
1765} else if (OB_FAIL(check_cancel())) {
1766LOG_WARN("check_cancel failed", KR(ret));
1767} else {
1768share::ObGlobalStatProxy proxy(*sql_proxy_, tenant_id);
1769uint64_t target_data_version = 0;
1770uint64_t current_data_version = 0;
1771uint64_t compatible_version = 0;
1772bool for_update = false;
1773if (OB_FAIL(proxy.get_target_data_version(for_update, target_data_version))) {
1774LOG_WARN("fail to get target data version", KR(ret), K(tenant_id));
1775} else if (OB_FAIL(proxy.get_current_data_version(current_data_version))) {
1776LOG_WARN("fail to get current data version", KR(ret), K(tenant_id));
1777} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compatible_version))) {
1778LOG_WARN("fail to get min data version", KR(ret), K(tenant_id));
1779} else if (target_data_version != current_data_version
1780|| target_data_version != compatible_version
1781|| target_data_version != DATA_CURRENT_VERSION) {
1782ret = OB_STATE_NOT_MATCH;
1783LOG_WARN("data_version not match, upgrade process should be run",
1784KR(ret), K(tenant_id), K(target_data_version),
1785K(current_data_version), K(compatible_version));
1786}
1787}
1788return ret;
1789}
1790
1791int ObRootInspection::check_cancel()
1792{
1793int ret = OB_SUCCESS;
1794if (stopped_) {
1795ret = OB_CANCELED;
1796} else if (OB_ISNULL(GCTX.root_service_)) {
1797ret = OB_ERR_UNEXPECTED;
1798LOG_WARN("rootservice is null", KR(ret));
1799} else if (!GCTX.root_service_->is_full_service()) {
1800ret = OB_CANCELED;
1801}
1802return ret;
1803}
1804
1805int ObRootInspection::check_tenant_status_(const uint64_t tenant_id)
1806{
1807int ret = OB_SUCCESS;
1808ObSchemaGetterGuard guard;
1809const ObSimpleTenantSchema *tenant = NULL;
1810int64_t schema_version = OB_INVALID_VERSION;
1811if (OB_ISNULL(schema_service_)) {
1812ret = OB_NOT_INIT;
1813LOG_WARN("schema service is null", KR(ret));
1814} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
1815LOG_WARN("fail to get schema guard", KR(ret));
1816} else if (OB_FAIL(guard.get_tenant_info(tenant_id, tenant))) {
1817LOG_WARN("fail to get tenant schema", KR(ret), K(tenant_id));
1818} else if (OB_ISNULL(tenant)) {
1819// tenant may has been dropped;
1820ret = OB_EAGAIN;
1821LOG_WARN("tenant may be dropped, don't continue", KR(ret), K(tenant_id));
1822} else if (!tenant->is_normal()) {
1823ret = OB_EAGAIN;
1824LOG_WARN("tenant status is not noraml, should check next round", KR(ret), K(tenant_id));
1825} else if (OB_FAIL(schema_service_->get_tenant_refreshed_schema_version(tenant_id, schema_version))) {
1826LOG_WARN("fail to get tenant schema version", KR(ret), K(tenant_id));
1827} else if (!ObSchemaService::is_formal_version(schema_version)) {
1828ret = OB_EAGAIN;
1829LOG_WARN("schema version is not formal, observer may be restarting or inner table schema changed, "
1830"should check next round", KR(ret), K(tenant_id), K(schema_version));
1831}
1832return ret;
1833}
1834
1835ObUpgradeInspection::ObUpgradeInspection()
1836: inited_(false), schema_service_(NULL), root_inspection_(NULL)
1837{
1838}
1839
1840ObUpgradeInspection::~ObUpgradeInspection()
1841{
1842}
1843
1844int ObUpgradeInspection::init(ObMultiVersionSchemaService &schema_service,
1845ObRootInspection &root_inspection)
1846{
1847int ret = OB_SUCCESS;
1848if (inited_) {
1849ret = OB_INIT_TWICE;
1850LOG_WARN("init twice", K(ret));
1851} else {
1852schema_service_ = &schema_service;
1853root_inspection_ = &root_inspection;
1854inited_ = true;
1855}
1856return ret;
1857}
1858
1859int ObUpgradeInspection::inner_get_next_row(common::ObNewRow *&row)
1860{
1861int ret = OB_SUCCESS;
1862ObSchemaGetterGuard schema_guard;
1863if (NULL == allocator_) {
1864ret = OB_NOT_INIT;
1865LOG_WARN("not init, allocator is null", K(ret));
1866} else if (!inited_) {
1867ret = OB_NOT_INIT;
1868LOG_WARN("not init", K(ret));
1869} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
1870LOG_WARN("get schema guard error", K(ret));
1871} else if (!start_to_read_) {
1872const ObTableSchema *table_schema = NULL;
1873const uint64_t table_id = OB_ALL_VIRTUAL_UPGRADE_INSPECTION_TID;
1874if (OB_FAIL(schema_guard.get_table_schema(OB_SYS_TENANT_ID, table_id, table_schema))) {
1875LOG_WARN("get_table_schema failed", K(table_id), K(ret));
1876} else if (NULL == table_schema) {
1877ret = OB_ERR_UNEXPECTED;
1878LOG_WARN("table_schema is null", KP(table_schema), K(ret));
1879} else {
1880ObArray<Column> columns;
1881
1882#define ADD_ROW(name, info) \
1883do { \
1884columns.reuse(); \
1885if (OB_FAIL(ret)) { \
1886} else if (OB_FAIL(get_full_row(table_schema, name, info, columns))) { \
1887LOG_WARN("get_full_row failed", "table_schema", *table_schema, \
1888K(name), K(info), K(ret)); \
1889} else if (OB_FAIL(project_row(columns, cur_row_))) { \
1890LOG_WARN("project_row failed", K(columns), K(ret)); \
1891} else if (OB_FAIL(scanner_.add_row(cur_row_))) { \
1892LOG_WARN("add_row failed", K(cur_row_), K(ret)); \
1893} \
1894} while (false)
1895
1896#define CHECK_RESULT(checked, value) (checked ? (value ? "succeed" : "failed") : "checking")
1897
1898ADD_ROW("zone_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1899root_inspection_->is_zone_passed()));
1900ADD_ROW("sys_stat_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1901root_inspection_->is_sys_stat_passed()));
1902ADD_ROW("sys_param_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1903root_inspection_->is_sys_param_passed()));
1904ADD_ROW("sys_table_schema_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1905root_inspection_->is_sys_table_schema_passed()));
1906ADD_ROW("data_version_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1907root_inspection_->is_data_version_passed()));
1908
1909bool upgrade_job_passed = true;
1910for (int64_t i = 0; OB_SUCC(ret) && i < UPGRADE_JOB_TYPE_COUNT; i++) {
1911int tmp = OB_SUCCESS;
1912ObRsJobType job_type = upgrade_job_type_array[i];
1913if (job_type > JOB_TYPE_INVALID && job_type < JOB_TYPE_MAX) {
1914if (OB_SUCCESS != (tmp = ObUpgradeUtils::check_upgrade_job_passed(job_type))) {
1915LOG_WARN("fail to check upgrade job passed", K(tmp), K(job_type));
1916upgrade_job_passed = false;
1917}
1918ADD_ROW(ObRsJobTableOperator::get_job_type_str(job_type),
1919CHECK_RESULT(root_inspection_->is_all_checked(), (OB_SUCCESS == tmp)));
1920}
1921}
1922
1923ADD_ROW("all_check", CHECK_RESULT(root_inspection_->is_all_checked(),
1924(root_inspection_->is_all_passed() && upgrade_job_passed)));
1925
1926#undef CHECK_RESULT
1927#undef ADD_ROW
1928}
1929if (OB_SUCC(ret)) {
1930scanner_it_ = scanner_.begin();
1931start_to_read_ = true;
1932}
1933}
1934if (OB_SUCC(ret)) {
1935if (OB_FAIL(scanner_it_.get_next_row(cur_row_))) {
1936if (OB_ITER_END != ret) {
1937LOG_WARN("get_next_row failed", K(ret));
1938}
1939} else {
1940row = &cur_row_;
1941}
1942}
1943return ret;
1944
1945}
1946
1947int ObUpgradeInspection::get_full_row(const share::schema::ObTableSchema *table,
1948const char *name, const char *info,
1949ObIArray<Column> &columns)
1950{
1951int ret = OB_SUCCESS;
1952if (!inited_) {
1953ret = OB_NOT_INIT;
1954LOG_WARN("not init", K(ret));
1955} else if (NULL == table || NULL == name || NULL == info) {
1956ret = OB_INVALID_ARGUMENT;
1957LOG_WARN("invalid argument", KP(table), KP(name), KP(info), K(ret));
1958} else {
1959ADD_COLUMN(set_varchar, table, "name", name, columns);
1960ADD_COLUMN(set_varchar, table, "info", info, columns);
1961}
1962
1963return ret;
1964}
1965
1966}//end namespace rootserver
1967}//end namespace oceanbase
1968