patch 4.1 bug fix and remove some secret url

This commit is contained in:
ob-robot 2023-03-19 19:22:48 +08:00
parent 8ce2f275c4
commit 9365c0dd4c
85 changed files with 1094 additions and 374 deletions

View File

@ -23,8 +23,8 @@
https://github.com/mcmilk/zstdmt
http://www.xxhash.com
http://www.example.com*
https://yuque.antfin-inc.com*
https://yuque.antfin.com*
@ -36,7 +36,7 @@
https://github.com/akopytov/sysbench*
http://foo.bar.com*
https://github.com/google/*
issue*
http://llvm.org/bugs*
https://bugs.llvm.org/*
http://www.apache.org/licenses/*
@ -177,9 +177,9 @@
http://docs.oracle.com/*
https://oracle-base.com/*
https://www.kernel.org/doc/*
https://www.atatech.org/*
http://www.atatech.org/*
http://oceanbase.alibaba-inc.com/*
https://community.oracle.com/tech/*
https://docs.docker.com/*
http://helloworld.com/*
@ -214,9 +214,9 @@
https://www.mathjax.org
https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/.
https://issues.apache.org/*
https://www.atatech.org/*
**/*.result
**/*.result
*
http://oracle.chinaitlab.com*
http://bugfree.corp.taobao.com*
https://www.baidu.com/*
@ -291,7 +291,7 @@
14844887@sina.com
**/*.test
http://trade.taobao.com/trade/*
*
http://oracle.chinaitlab.com*
http://bugfree.corp.taobao.com*
https://www.baidu.com/*
@ -366,7 +366,7 @@
14844887@sina.com
**/*.inc
http://trade.taobao.com/trade/*
*
http://oracle.chinaitlab.com*
http://bugfree.corp.taobao.com*
https://www.baidu.com/*

View File

@ -613,7 +613,7 @@ private:
WLockGuard guard(sn_dir_lock_);
set_dir_(new_dir); // Replace. It's caller's duty to retire Dir & Segment.
// Ensure atomicity of updating begin_sn_ & Dir
// https://yuque.antfin.com/docs/share/22158f7c-5375-4d0c-953a-d43b7614d2dc?#
//
update_begin_sn_(ctrl_sn+1);
}
esunlock_();

View File

@ -39,6 +39,9 @@ void ObRetryPolicy::try_packet_retry(ObRetryParam &v) const
const ObMultiStmtItem &multi_stmt_item = v.ctx_.multi_stmt_item_;
if (v.force_local_retry_) {
v.retry_type_ = RETRY_TYPE_LOCAL;
} else if (multi_stmt_item.is_batched_multi_stmt()) {
// in batch optimization, can't do packet retry
v.retry_type_ = RETRY_TYPE_LOCAL;
} else if (multi_stmt_item.is_part_of_multi_stmt() && multi_stmt_item.get_seq_num() > 0) {
// muti stmt,并且不是第一句,不能扔回队列重试,因为前面的无法回滚
v.retry_type_ = RETRY_TYPE_LOCAL;

View File

@ -239,10 +239,15 @@ int ObSyncPlanDriver::response_result(ObMySQLResultSet &result)
!admission_fail_and_need_retry
&& OB_BATCHED_MULTI_STMT_ROLLBACK != ret) {
//OB_BATCHED_MULTI_STMT_ROLLBACK如果是batch stmt rollback错误,不要返回给客户端,退回到mpquery上重试
int sret = OB_SUCCESS;
bool is_partition_hit = session_.get_err_final_partition_hit(ret);
if (OB_SUCCESS != (sret = sender_.send_error_packet(ret, NULL, is_partition_hit))) {
LOG_WARN("send error packet fail", K(sret), K(ret));
if (ctx_.multi_stmt_item_.is_batched_multi_stmt()) {
// The error of batch optimization execution does not need to send error packet here,
// because the upper layer will force a fallback to a single line execution retry
} else {
int sret = OB_SUCCESS;
bool is_partition_hit = session_.get_err_final_partition_hit(ret);
if (OB_SUCCESS != (sret = sender_.send_error_packet(ret, NULL, is_partition_hit))) {
LOG_WARN("send error packet fail", K(sret), K(ret));
}
}
}
ObActiveSessionGuard::get_stat().in_sql_execution_ = false;

View File

@ -2057,7 +2057,7 @@ int ObMPConnect::update_charset_sys_vars(ObSMConnection &conn, ObSQLSessionInfo
// default charset for mysqltest
//TODO: after obclient&mysqltest support default charset = utf8
// login for cs_type != LATIN1_CS would be deleted
if (cs_type != LATIN1_CS && ObCharset::is_valid_collation(cs_type)) {
if (ObCharset::is_valid_collation(cs_type)) {
if (OB_FAIL(sess_info.update_sys_variable(SYS_VAR_CHARACTER_SET_CLIENT, cs_type))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(sess_info.update_sys_variable(SYS_VAR_CHARACTER_SET_RESULTS, cs_type))) {

View File

@ -611,6 +611,7 @@ int ObMPPacketSender::send_ok_packet(ObSQLSessionInfo &session, ObOKPParam &ok_p
}
} else if (conn_->is_driver_client()) {
// will not track session variables, do nothing
okp.set_use_standard_serialize(true);
} else {
if (OB_FAIL(ObMPUtils::add_changed_session_info(okp, session))) {
SERVER_LOG(WARN, "fail to add changed session info", K(ret));

View File

@ -480,17 +480,16 @@ int ObMPQuery::try_batched_multi_stmt_optimization(sql::ObSQLSessionInfo &sessio
force_sync_resp,
async_resp_used,
need_disconnect))) {
if (OB_BATCHED_MULTI_STMT_ROLLBACK == ret) {
ret = OB_SUCCESS;
LOG_TRACE("batched multi_stmt needs rollback", K(ret));
} else {
LOG_WARN("failed to process single stmt", K(ret));
}
int tmp_ret = ret;
ret = OB_SUCCESS;
LOG_WARN("failed to process batch stmt, cover the error code and reset retry flag",
K(tmp_ret), K(ret), K(THIS_WORKER.need_retry()));
} else {
optimization_done = true;
}
LOG_TRACE("succeed to try batched multi-stmt optimization", K(optimization_done),
K(ret), K(queries.count()), K(enable_batch_opt));
LOG_TRACE("after to try batched multi-stmt optimization", K(optimization_done),
K(queries), K(enable_batch_opt), K(ret), K(THIS_WORKER.need_retry()), K(retry_ctrl_.need_retry()), K(retry_ctrl_.get_retry_type()));
return ret;
}
@ -795,6 +794,9 @@ OB_INLINE int ObMPQuery::do_process(ObSQLSessionInfo &session,
// 所以此时可以同步回包,设置need_response_error
// 向客户端返回一个error包,表示需要二次路由
need_response_error = true;
} else if (ctx_.multi_stmt_item_.is_batched_multi_stmt()) {
// batch execute with error,should not response error packet
need_response_error = false;
} else if (OB_BATCHED_MULTI_STMT_ROLLBACK == ret) {
need_response_error = false;
}

View File

@ -1542,13 +1542,17 @@ int ObMPStmtExecute::try_batch_multi_stmt_optimization(ObSQLSessionInfo &session
LOG_TRACE("batched multi_stmt needs rollback", K(ret));
ret = OB_SUCCESS;
} else {
LOG_WARN("failed to process single stmt", K(ret));
// 无论什么报错,都走单行执行一次,用于容错
int ret_tmp = ret;
ret = OB_SUCCESS;
LOG_WARN("failed to process batch stmt, cover the error code, reset retry flag, then execute with single row",
K(ret_tmp), K(ret), K(THIS_WORKER.need_retry()));
}
} else {
optimization_done = true;
}
LOG_TRACE("after try batched multi-stmt optimization", K(ret), K(stmt_type_), K(use_plan_cache),
K(optimization_done), K(enable_batch_opt), K(is_ab_returning), K(arraybinding_size_));
K(optimization_done), K(enable_batch_opt), K(is_ab_returning), K(THIS_WORKER.need_retry()), K(arraybinding_size_));
return ret;
}

View File

@ -285,7 +285,7 @@ int ObMPStmtPrexecute::before_process()
LOG_WARN("prepare-execute protocol get params request failed", K(ret));
} else {
ObMySQLUtil::get_uint4(pos, exec_mode_);
// https://yuque.antfin.com/docs/share/a5705d97-1d74-4b90-8be2-6e500249345f?#
//
// is_commit_on_success_ is not use yet
// other exec_mode set use ==
is_commit_on_success_ = exec_mode_ & OB_OCI_COMMIT_ON_SUCCESS;

View File

@ -176,7 +176,7 @@ void ObTenantConfigMgr::refresh_config_version_map(const ObIArray<uint64_t> &ten
// 背景:每个 server 上需要保存所有租户的 config 信息
// 当新建租户/删除租户时需要对应维护 config 状态。
// https://yuque.antfin-inc.com/xiaochu.yh/doc/zf2eqy/
//
// IN: 当前活跃租户
// ACTION: 根据 tenants 信息,决定要添加/删除哪些租户配置项
int ObTenantConfigMgr::refresh_tenants(const ObIArray<uint64_t> &tenants)

View File

@ -223,6 +223,7 @@ int ObTableLoadMerger::build_merge_ctx()
table_array = &empty_table_array;
}
if (!merge_param.is_heap_table_ && !table_array->empty()) {
// for optimize split range is too slow
ObArray<ObDirectLoadMultipleSSTable *> multiple_sstable_array;
ObDirectLoadMultipleMergeRangeSplitter range_splitter;
for (int64_t i = 0; OB_SUCC(ret) && i < table_array->count(); ++i) {
@ -247,6 +248,16 @@ int ObTableLoadMerger::build_merge_ctx()
LOG_WARN("fail to build merge task for multiple pk table", KR(ret));
}
}
} else if (merge_param.is_heap_table_ && !table_array->empty() &&
tablet_merge_ctxs.count() > param_.session_count_ * 2) {
// for optimize the super multi-partition heap table space serious enlargement
for (int64_t i = 0; OB_SUCC(ret) && i < tablet_merge_ctxs.count(); ++i) {
ObDirectLoadTabletMergeCtx *tablet_merge_ctx = tablet_merge_ctxs.at(i);
if (OB_FAIL(
tablet_merge_ctx->build_aggregate_merge_task_for_multiple_heap_table(*table_array))) {
LOG_WARN("fail to build aggregate merge task for multiple heap table", KR(ret));
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < tablet_merge_ctxs.count(); ++i) {
ObDirectLoadTabletMergeCtx *tablet_merge_ctx = tablet_merge_ctxs.at(i);

View File

@ -732,7 +732,7 @@ int ObVirtualSqlPlanMonitor::convert_node_to_row(ObMonitorNode &node, ObNewRow *
break;
}
case DB_TIME: {
// concept: https://yuque.antfin.com/xiaochu.yh/doc/lt4toe/
// concept:
cells[cell_idx].set_int(node.db_time_);
break;
}

View File

@ -591,7 +591,7 @@ public:
* some package subprogram has special invoker right, though the package may have definer privs
* for example: dbms_utility package is definer privs, but some function such as
* name_resolve must be run as current_user, oracle do it in interface functions
* see: https://yuque.antfin.com/docs/share/990f729a-d21b-47f1-94ec-6b4b5cda950f?# 《oracle如何实现一个包中同时控制多个权限(sys, current_user)》
* see:
* we hacked it using name compared, for the interface funtion can't get the origin db name and id
* test -> oceanbase, we see oceanbase in interface but can't see test.
*/

View File

@ -518,7 +518,7 @@ protected:
// for ObServerBalancer
IdPoolMap& get_id_pool_map() { return id_pool_map_; }
TenantPoolsMap& get_tenant_pools_map() { return tenant_pools_map_; }
// bug#11873101
// bug#11873101 issue/11873101
// Before attempting to migrate the unit,
// check whether the target unit space is sufficient,
// if it is insufficient, do not migrate,

View File

@ -28,7 +28,7 @@
# sys_agent access tables belong to sys tenant only
# real_agent access tables belong to current tenant
# 8. Virtual table system design summary:
# https://yuque.antfin.com/docs/share/876fb26e-7466-476f-bd67-b3c4860fbdb8?#
#
# 9. For compatibility, when add new column for system table, new column's definition should be "not null + default value" or "nullable".
# Specially, when column types are as follows:
# 1. double、number:default value is not supported, so new column definition should be "nullable".

View File

@ -167,7 +167,7 @@ struct TableNode: public common::LinkHashValue<AutoincKey>
// we are not sure if curr_node is avaliable.
// it will become avaliable again after fetch a new node
// and combine them together.
// ref: https://yuque.antfin-inc.com/xiaochu.yh/doc/eqnlv0
// ref:
bool curr_node_state_is_pending_;
int64_t autoinc_version_;
};

View File

@ -1,4 +1,4 @@
// @see http://oceanbase.alibaba-inc.com/wiki/index.php?title=%E9%94%99%E8%AF%AF%E7%A0%81%E7%9A%84%E8%A7%84%E8%8C%83
// @see
// 10000
// 使[-1, -4000)MySQL目的使用MySQL Server端错误码范围1000-30002000-3000, 1-1000Oracle的常用错误码的范围大约在这个范围内
// [-4000, -4500)sstable等

View File

@ -12490,7 +12490,7 @@ int ObObjCaster::to_type(const ObObjType expect_type,
const ObObjTypeClass out_tc = ob_obj_type_class(expect_type);
cast_ctx.warning_ = OB_SUCCESS;
/* expect_cs_type has higer priority than cast_ctx.dest_collation_
*/
if (CS_TYPE_INVALID != expect_cs_type) {
cast_ctx.dest_collation_ = expect_cs_type;
} else {
@ -12794,7 +12794,7 @@ int ObObjCaster::is_const_consistent(const ObObjMeta &const_mt,
/* make sure that you have read the doc before you call these functions !
*
* doc: http://www.atatech.org/articles/56575
* doc:
*/
int ObObjCaster::is_order_consistent(const ObObjMeta &from,
@ -12842,7 +12842,7 @@ int ObObjCaster::is_order_consistent(const ObObjMeta &from,
/* make sure that you have read the doc before you call these functions !
*
* doc: http://www.atatech.org/articles/56575
* doc:
*/
int ObObjCaster::is_injection(const ObObjMeta &from,

View File

@ -7212,7 +7212,7 @@ int ObPartitionUtils::calc_hash_part_idx(const uint64_t val,
const static int64_t max_part_num_log2 = 64;
// This function is used by SQL. Should ensure SQL runs in MySQL mode when query sys table.
if (lib::is_oracle_mode()) {
// https://yuque.antfin-inc.com/ob-public/sql/sfaedg
//
// It will not be a negative number, so use forced conversion instead of floor
N = static_cast<int64_t>(std::log(part_num) / std::log(2));
if (N >= max_part_num_log2) {

View File

@ -276,7 +276,7 @@ int ObDbmsStatsMaintenanceWindow::get_dummy_guard_job_sql(const uint64_t tenant_
* FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22; 4 hours
* SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6; 20 hours
* SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6; 20 hours
* https://yuque.antfin-inc.com/docs/share/05d01692-f9e6-42de-99cf-365fccc45974?# 《统计信息maintenance window设计与实现》
*
*/
int ObDbmsStatsMaintenanceWindow::get_window_job_info(const int64_t current_time,
const int64_t nth_window,

View File

@ -319,7 +319,7 @@ bool ObDbmsStatsUtils::is_virtual_index_table(const int64_t table_id)
* PARTITION: Gather partition-level
* SUBPARTITION: Gather subpartition-level
* Oracle granularity actual behavior survey:
* https://yuque.antfin-inc.com/docs/share/3eeffde1-7182-4b2a-8f01-e7a3045d4d1e?#
*
* @return
*/
int ObDbmsStatsUtils::parse_granularity(const ObString &granularity,

View File

@ -393,7 +393,7 @@ int ObBasicSysVar::session_update(ObExecContext &ctx,
}
} else if (set_var.var_name_ == OB_SV__ENABLE_PARALLEL_QUERY) {
should_update_extra_var = true;
// https://yuque.antfin-inc.com/xiaochu.yh/doc/exgk9g/
//
// 实现 Oracle 兼容行为方式如下:有变量 enable 和 parallel
// alter session enable parallel query 时 enable = true, parallel = 1 => 走 manual table dop 规则
// alter session disable parallel query 时 enable = false, parallel = 1 => 走 no parallel 规则

View File

@ -650,7 +650,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"query_cache_type": {
"id": 45,
@ -667,7 +667,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"sql_quote_show_create": {
"id": 46,
@ -916,7 +916,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"ssl_ca": {
"id": 66,
@ -1110,7 +1110,7 @@
"publish_version": "312",
"info_cn": "控制返回的ok包中是否包含schema变更的信息",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"session_track_system_variables": {
"id": 82,
@ -1122,7 +1122,7 @@
"publish_version": "312",
"info_cn": "控制返回的ok包中是否包含系统变量变更的信息",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"session_track_state_change": {
"id": 83,
@ -1134,7 +1134,7 @@
"publish_version": "312",
"info_cn": "控制返回的ok包中是否包含session状态变更的信息",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"have_query_cache": {
"id": 84,
@ -1146,7 +1146,7 @@
"publish_version": "323",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"query_cache_limit": {
"id": 85,
@ -1160,7 +1160,7 @@
"publish_version": "323",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"query_cache_min_res_unit": {
"id": 86,
@ -1174,7 +1174,7 @@
"publish_version": "323",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"query_cache_wlock_invalidate": {
"id": 87,
@ -1186,7 +1186,7 @@
"publish_version": "323",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"binlog_format": {
"id": 88,
@ -1203,7 +1203,7 @@
"publish_version": "324",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"binlog_checksum": {
"id": 89,
@ -1215,7 +1215,7 @@
"publish_version": "324",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"binlog_rows_query_log_events": {
"id": 90,
@ -1227,7 +1227,7 @@
"publish_version": "324",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"log_bin": {
"id": 91,
@ -1239,7 +1239,7 @@
"publish_version": "324",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"server_uuid": {
"id": 92,
@ -1251,7 +1251,7 @@
"publish_version": "324",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"default_storage_engine": {
"id": 93,
@ -1277,7 +1277,7 @@
"publish_version": "400",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"regexp_stack_limit": {
"id": 95,
@ -2494,7 +2494,7 @@
"publish_version": "226",
"info_cn": "限制导入导出功能访问的路径",
"background_cn": "导入导出功能未限制文件访问可能存在漏洞",
"ref_url": "
"ref_url": ""
},
"plsql_warnings": {
"id": 10103,
@ -2507,7 +2507,7 @@
"publish_version": "3.1.0",
"info_cn": "控制pl/sql编译器的报错行为,可以指定某类型或某个warning码的状态为:enable,disable,error",
"background_cn": "pl/sql编译器的警告信息分成了几个分类,这个系统参数可以控制这些警告信息的行为",
"ref_url": "
"ref_url": ""
},
"_enable_parallel_query": {
"id": 10104,
@ -2519,7 +2519,7 @@
"publish_version": "227",
"info_cn": "在session上打开parallel query配置项,查询默认情况下才可以被并行执行(parallel>=2)",
"background_cn": "px上控制parallel的方式有很多,session上有对应的parallel的控制开关,这个开关用于控制session级别的默认并行度是否可以大于等于2",
"ref_url": "
"ref_url": ""
},
"_force_parallel_query_dop": {
"id": 10105,
@ -2531,7 +2531,7 @@
"publish_version": "310",
"info_cn": "在session上打开parallel query配置项,并指定默认并行度",
"background_cn": "px上控制parallel的方式有很多,session上有对应的parallel的控制开关,这个变量用于设置session级别的 query 默认并行度大小",
"ref_url": "
"ref_url": ""
},
"_force_parallel_dml_dop": {
"id": 10106,
@ -2543,7 +2543,7 @@
"publish_version": "310",
"info_cn": "在session上打开parallel dml配置项,并指定默认并行度。当未通过 hint 指定 dml 并行度时,会使用本变量值作为默认并行度",
"background_cn": "px上控制parallel的方式有很多,session上有对应的parallel的控制开关,这个变量用于设置session级别的 dml 默认并行度大小",
"ref_url": "
"ref_url": ""
},
"ob_pl_block_timeout": {
"id": 10107,
@ -2558,7 +2558,7 @@
"publish_version": "227",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"transaction_read_only": {
"id": 10108,
@ -2574,7 +2574,7 @@
"publish_version": "320",
"info_cn": "控制是否只允许开启只读事务",
"background_cn": "用户可以通过这两个变量访问或者设置事务的访问模式,当transaction_read_only设置为true时,不允许执行dml语句",
"ref_url": "
"ref_url": ""
},
"resource_manager_plan": {
"id": 10109,
@ -2587,7 +2587,7 @@
"publish_version": "320",
"info_cn": "指定租户的资源隔离计划",
"background_cn": "租户内的普通线程和并行执行线程会相互抢占CPU资源,通过给租户指定资源隔离计划,可以控制资源抢占策略,隔离资源使用量",
"ref_url": "
"ref_url": ""
},
"performance_schema": {
"id": 10110,
@ -2599,7 +2599,7 @@
"publish_version": "227",
"info_cn": "向客户端声明是否支持 performance 信息查询",
"background_cn": "纯兼容性变量。不支持 performance_schema 系统变量,导致 8.0 JDBC 驱动在连接认证后初始化系统变量阶段执行 select @performance_schema 抛出异常",
"ref_url": "
"ref_url": ""
},
"nls_currency": {
"id": 10111,
@ -2612,7 +2612,7 @@
"publish_version": "320",
"info_cn": "L数字格式元素的本地货币符号",
"background_cn": "兼容 oracle number format model L 数字格式元素",
"ref_url": "
"ref_url": ""
},
"nls_iso_currency": {
"id": 10112,
@ -2625,7 +2625,7 @@
"publish_version": "320",
"info_cn": "C数字格式元素的国际货币符号",
"background_cn": "兼容 oracle number format model C 数字格式元素",
"ref_url": "
"ref_url": ""
},
"nls_dual_currency": {
"id": 10113,
@ -2638,7 +2638,7 @@
"publish_version": "320",
"info_cn": "U数字格式元素的双货币符号",
"background_cn": "兼容 oracle number format model U 数字格式元素",
"ref_url": "
"ref_url": ""
},
"plsql_ccflags" : {
"id": 10115,
@ -2651,7 +2651,7 @@
"publish_version": "330",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_ob_proxy_session_temporary_table_used": {
"id": 10116,
@ -2663,7 +2663,7 @@
"publish_version": "310",
"info_cn": "标记当前Session是否使用过Session级别临时表,用于告知proxy并修改路由决策",
"background_cn": "为了解决Session临时表断链接时可能导致的问题,当Session临时表第一次使用后,后续请求Proxy只会路由到同一个Session",
"ref_url": "
"ref_url": ""
},
"_enable_parallel_ddl": {
"id": 10117,
@ -2675,7 +2675,7 @@
"publish_version": "330",
"info_cn": "标记Session上并行DDL是否被打开",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_force_parallel_ddl_dop": {
"id": 10118,
@ -2687,7 +2687,7 @@
"publish_version": "330",
"info_cn": "在session上打开parallel ddl配置项,并指定默认并行度。当未通过 hint 指定 ddl 并行度时,会使用本变量值作为默认并行度",
"background_cn": "ddl上控制parallel的方式有很多,session上有对应的parallel的控制开关,这个变量用于设置session级别的 ddl 默认并行度大小",
"ref_url": "
"ref_url": ""
},
"cursor_sharing": {
"id": 10119,
@ -2703,7 +2703,7 @@
"publish_version": "330",
"info_cn": "在session上打开控制是否参数化的配置项。当处于exact模式时,不进行参数化;处于Force模式时,进行参数化。默认进行参数化。",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_optimizer_null_aware_antijoin": {
"id": 10120,
@ -2715,7 +2715,7 @@
"publish_version": "330",
"info_cn": "控制优化器能否生成null aware anti join 的计划",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_px_partial_rollup_pushdown": {
"id": 10121,
@ -2759,7 +2759,7 @@
"publish_version": "330",
"info_cn": "创建mysql模式的审计日志定期清理任务",
"background_cn": "示例: create_audit_purge_job='trail_type:interval:jobname:use_last_archive_timestamp'",
"ref_url": "
"ref_url": ""
},
"_drop_audit_purge_job": {
"id": 10124,
@ -2771,7 +2771,7 @@
"publish_version": "330",
"info_cn": "删除mysql模式的审计日志定期清理任务",
"background_cn": "示例: drop_audit_purge_job='jobname'",
"ref_url": "
"ref_url": ""
},
"_set_purge_job_interval": {
"id": 10125,
@ -2783,7 +2783,7 @@
"publish_version": "330",
"info_cn": "更新purge job的interval时间",
"background_cn": "示例: set_purge_job_interval='jobname:interval'",
"ref_url": "
"ref_url": ""
},
"_set_purge_job_status": {
"id": 10126,
@ -2795,7 +2795,7 @@
"publish_version": "330",
"info_cn": "更新purge job的状态,控制job是否生效",
"background_cn": "示例: set_purge_job_status='jobname:status'",
"ref_url": "
"ref_url": ""
},
"_set_last_archive_timestamp": {
"id": 10127,
@ -2807,7 +2807,7 @@
"publish_version": "330",
"info_cn": "设置删除的时间点信息,需要使用从1970开始的utc时间,微妙为单位",
"background_cn": "示例: set_last_archive_timestamp='trail_type:timestamp'",
"ref_url": "
"ref_url": ""
},
"_clear_last_archive_timestamp": {
"id": 10128,
@ -2819,7 +2819,7 @@
"publish_version": "330",
"info_cn": "清除删除的时间点信息",
"background_cn": "示例: clear_last_archive_timestamp='trail_type'",
"ref_url": "
"ref_url": ""
},
"_aggregation_optimization_settings": {
"id": 10129,
@ -2831,7 +2831,7 @@
"publish_version": "330",
"info_cn": "",
"background_cn": "用于调优group by 和distinct的执行行为",
"ref_url": "
"ref_url": ""
},
"_px_shared_hash_join": {
"id": 10130,
@ -2855,7 +2855,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"innodb_strict_mode": {
"id": 10132,
@ -2867,7 +2867,7 @@
"publish_version": "400",
"info_cn": "特定场合下,警告会当成错误返回",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_windowfunc_optimization_settings": {
"id": 10133,
@ -2881,7 +2881,7 @@
"publish_version": "400",
"info_cn": "window function优化设置",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"ob_enable_rich_error_msg": {
"id": 10134,
@ -2893,7 +2893,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"log_row_value_options": {
"id": 10136,
@ -2906,7 +2906,7 @@
"publish_version": "",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"ob_max_read_stale_time": {
"id": 10137,
@ -2919,7 +2919,7 @@
"publish_version": "410",
"info_cn": "",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_optimizer_gather_stats_on_load": {
"id": 10138,
@ -2931,7 +2931,7 @@
"publish_version": "400",
"info_cn": "控制在insert into select下是否默认收集统计信息",
"background_cn": "",
"ref_url": "
"ref_url": ""
},
"_set_reverse_dblink_infos": {
"id": 10139,
@ -2943,6 +2943,6 @@
"publish_version": "410",
"info_cn": "用于dblink写事务中, TM端通过设置系统变量的方式告知RM端关于建立反向dblink的必要信息",
"background_cn": "",
"ref_url": "
"ref_url": ""
}
}

View File

@ -403,7 +403,7 @@ class ObNoRetry : public ObIRetryPolicy
{};
/// consistency levels
/// @see https://www.atatech.org/articles/102030
/// @see
enum class ObTableConsistencyLevel
{
STRONG = 0,

View File

@ -2566,7 +2566,7 @@ int ObDmlCgService::generate_fk_arg(ObForeignKeyArg &fk_arg,
} else if (fk_arg.is_self_ref_
&& !var_exist_in_array(column_ids, name_column_ids.at(i), fk_column.name_idx_)) {
/**
*
* issue/18132630
* fk_column.name_idx_ is used only for self ref row, that is to say name table and
* value table is same table.
* otherwise name_column_ids.at(i) will indicate columns in name table, not value table,

View File

@ -312,7 +312,7 @@ int ObDblinkUtils::process_dblink_errno(common::sqlclient::DblinkDriverProto dbl
return OB_SUCCESS;
}
int ObDblinkUtils::has_reverse_link(const ObDMLStmt *stmt, bool &has) {
int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink) {
int ret = OB_SUCCESS;
const common::ObIArray<TableItem*> &table_items = stmt->get_table_items();
ObArray<ObSelectStmt*> child_stmts;
@ -321,12 +321,16 @@ int ObDblinkUtils::has_reverse_link(const ObDMLStmt *stmt, bool &has) {
if (OB_ISNULL(table_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null ptr", K(ret));
} else if (table_item->is_reverse_link_) {
} else if (has_any_dblink && (table_item->is_reverse_link_ || OB_INVALID_ID != table_item->dblink_id_)) {
has = true;
LOG_DEBUG("succ to find reverse link", K(table_item), K(i));
break;
} else if (!has_any_dblink && table_item->is_reverse_link_) {
has = true;
LOG_DEBUG("succ to find reverse link", K(table_item), K(i));
break;
} else if (table_item->is_temp_table()) {
if (OB_FAIL(SMART_CALL(has_reverse_link(table_item->ref_query_, has)))) {
if (OB_FAIL(SMART_CALL(has_reverse_link_or_any_dblink(table_item->ref_query_, has, has_any_dblink)))) {
LOG_WARN("failed to exec has_reverse_link", K(ret));
} else if (has) {
break;
@ -342,7 +346,7 @@ int ObDblinkUtils::has_reverse_link(const ObDMLStmt *stmt, bool &has) {
if (OB_ISNULL(child_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null ptr", K(ret));
} else if (OB_FAIL(SMART_CALL(has_reverse_link(child_stmt, has)))) {
} else if (OB_FAIL(SMART_CALL(has_reverse_link_or_any_dblink(child_stmt, has, has_any_dblink)))) {
LOG_WARN("failed to exec has_reverse_link", K(ret));
} else if (has) {
break;

View File

@ -101,7 +101,7 @@ class ObDblinkUtils
public:
static int process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, common::sqlclient::ObISQLConnection *dblink_conn, int &ob_errno);
static int process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, int &ob_errno);
static int has_reverse_link(const ObDMLStmt *stmt, bool &has);
static int has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink = false);
};
class ObSQLSessionInfo;

View File

@ -29,7 +29,7 @@ namespace dtl {
* transmit和receive端直接根据创建好的channel信息来new channel实例
* transmit_dfo_task_cnt * receive_dfo_task_cntdop=512512*512
* dop增大耗时更长bug
* https://yuque.antfin-inc.com/docs/share/fd7b13c8-9e42-4950-a642-5627db3abb2c?# 《DTL channel map优化设计》
*
* PX端不再构建所有channel具体信息
* PX构建channel的总体信息channel总体信息发给所有的dfo的sqc
* (task)worker根据channel总体信息各自构建自己的信息,

View File

@ -170,7 +170,7 @@ OB_INLINE int ObTableInsertOp::open_table_for_each()
//this table is being accessed by dml operator, mark its table location as writing
//but single value insert in oracle allow the nested sql modify its insert table
//clear the writing flag in table location before the trigger execution
//see it:https://yuque.antfin-inc.com/docs/share/40291dac-859c-48de-8a31-79bb7ca7c571
//see it:
primary_ins_rtdef.das_rtdef_.table_loc_->is_writing_ =
!(primary_ins_ctdef.is_single_value_ && lib::is_oracle_mode());
}
@ -341,15 +341,6 @@ int ObTableInsertOp::write_rows_post_proc(int last_errno)
}
}
}
// all error, we must rollback with single execute when batch executed
if (OB_SUCCESS != ret && OB_ITER_END != ret) {
ObMultiStmtItem &multi_stmt_item = ctx_.get_sql_ctx()->multi_stmt_item_;
if (MY_SPEC.ins_ctdefs_.at(0).at(0)->das_ctdef_.is_batch_stmt_ && !multi_stmt_item.is_ins_multi_val_opt()) {
int tmp_ret = ret;
ret = OB_BATCHED_MULTI_STMT_ROLLBACK;
LOG_TRACE("batch exec with some exception, rollback with single execute", K(ret), K(tmp_ret));
}
}
return ret;
}

View File

@ -68,7 +68,6 @@ int ObExprChar::calc_result_typeN(ObExprResType &type, ObExprResType *types, int
} else {
//set calc type
//i starts from 1 rather than 0 since the first param is obvarchar always.
//see http://review.alibaba-inc.com/r/21109/ for more details when necessary.
for (int64_t i = 0; i < param_num-1; ++i) {
types[i].set_calc_type(ObIntType);
}

View File

@ -66,7 +66,7 @@ int ObExprOrahash::calc_result_typeN(ObExprResType &type,
return ret;
}
//算法详见 https://yuque.antfin-inc.com/ob-public/sql/sfaedg
//算法详见
uint64_t ObExprOrahash::hash_mod_oracle(uint64_t val, uint64_t buckets) const
{
uint64_t N = 1;

View File

@ -919,7 +919,7 @@ int ObOperator::submit_op_monitor_node()
if (GCONF.enable_sql_audit) {
// Record monitor info in sql_plan_monitor
// Some records that meets the conditions needs to be archived
// Reference document: https://yuque.antfin.com/baixian.zr/brtfzn/ppx26a
// Reference document:
op_monitor_info_.close_time_ = oceanbase::common::ObClockGenerator::getClock();
ObPlanMonitorNodeList *list = MTL(ObPlanMonitorNodeList*);
if (list && spec_.plan_) {

View File

@ -186,7 +186,7 @@ protected:
int64_t bf_ctx_idx_; // the idx of bloom_filter_id_array_ in spec
int64_t bf_send_idx_; // the idx of bf_send_ctx_array_ in sqc proxy
// each_group_size_ only used in ObPxMsgProc::mark_rpc_filter()(this func will calc group_size, then each_group_size_ keep it for next use)
// means how many node(sqc level) in this group https://yuque.antfin.com/mingdou.tmd/px/gcu6uz
// means how many node(sqc level) in this group
int64_t each_group_size_;
};

View File

@ -322,7 +322,7 @@ class ObGranulePump
private:
static const int64_t OB_GRANULE_SHARED_POOL_POS = 0;
// https://yuque.antfin-inc.com/docs/share/9b5fea38-dab7-46ee-bf02-98851def2de1?#
//
// 《PX的GI详细实现》
enum ObGranuleSplitterType
{

View File

@ -235,7 +235,7 @@ int ObInterruptUtil::generate_px_interrupt_id(const uint32_t server_id,
// 取低12位
timestamp = (uint64_t)0xfff & timestamp;
interrupt_id.first_ = px_sequence_id;
// https://yuque.antfin-inc.com/mingdou.tmd/px/xc70bl
//
// [ server_id (32bits) ][ qc_id (10bits)][ dfo_id (10bits) ][ timestamp (12bits) ]
interrupt_id.last_ = ((uint64_t)server_id) << 32 | (uint64_t)qc_id << 22 |
(uint64_t)dfo_id << 12 | (uint64_t)timestamp;

View File

@ -513,6 +513,7 @@ enum PXParallelRule
SESSION_FORCE_PARALLEL, // alter session force parallel query parallel 3;
MANUAL_TABLE_DOP, // create table t1 (...) parallel 3;
PL_UDF_DAS_FORCE_SERIALIZE, //stmt has_pl_udf will use das, force serialize;
DBLINK_FORCE_SERIALIZE, //stmt has dblink will use das, force seialize;
MAX_OPTION
};
@ -528,6 +529,7 @@ inline const char *ob_px_parallel_rule_str(PXParallelRule px_parallel_ruel)
"SESSION_FORCE_PARALLEL",
"MANUAL_TABLE_DOP",
"PL_UDF_DAS_FORCE_SERIALIZE",
"DBLINK_FORCE_SERIALIZE",
"MAX_OPTION",
};
if (OB_LIKELY(px_parallel_ruel >= NOT_USE_PX)

View File

@ -663,7 +663,7 @@ int ObSqlTransControl::stmt_setup_snapshot_(ObSQLSessionInfo *session,
bool local_single_ls_plan = plan->is_local_plan()
&& OB_PHY_PLAN_LOCAL == plan->get_location_type()
&& das_ctx.has_same_lsid(&local_ls_id);
if (local_single_ls_plan && !tx_desc.is_can_elr()) {
if (local_single_ls_plan) {
ret = txs->get_ls_read_snapshot(tx_desc,
session->get_tx_isolation(),
local_ls_id,

View File

@ -112,7 +112,7 @@ int ObDelUpdLogPlan::generate_dblink_raw_plan()
} else {
set_plan_root(top);
bool has_reverse_link = false;
if (OB_FAIL(ObDblinkUtils::has_reverse_link(stmt, has_reverse_link))) {
if (OB_FAIL(ObDblinkUtils::has_reverse_link_or_any_dblink(stmt, has_reverse_link))) {
LOG_WARN("failed to exec has_reverse_link", K(ret));
} else {
uint64_t dblink_id = stmt->get_dblink_id();

View File

@ -32,6 +32,7 @@ namespace sql
#define PARALLEL_ENABLED_BY_TABLE_PROPERTY "Degree of Parallelisim is %ld because of table property"
#define PARALLEL_DISABLED_BY_PL_UDF_DAS "Degree of Parallelisim is %ld because stmt contain pl_udf which force das scan"
#define DIRECT_MODE_INSERT_INTO_SELECT "Direct-mode is enabled in insert into select"
#define PARALLEL_DISABLED_BY_DBLINK "Degree of Parallelisim is %ld because stmt contain dblink which force das scan"
}
}

View File

@ -1270,6 +1270,7 @@ int ObJoinOrder::will_use_das(const uint64_t table_id,
bool hint_force_no_das = false;
force_das_tsc = get_plan()->get_optimizer_context().in_nested_sql() ||
get_plan()->get_optimizer_context().has_pl_udf() ||
get_plan()->get_optimizer_context().has_dblink() ||
get_plan()->get_optimizer_context().has_subquery_in_function_table() ||
is_batch_update_table;
//this sql force to use DAS TSC:

View File

@ -47,6 +47,14 @@ int ObLogLink::compute_sharding_info()
return ret;
}
int ObLogLink::compute_op_parallel_and_server_info()
{
int ret = OB_SUCCESS;
set_parallel(1);
set_server_cnt(1);
return ret;
}
int ObLogLink::est_cost()
{
int ret = OB_SUCCESS;

View File

@ -38,6 +38,7 @@ public:
virtual ~ObLogLink() {}
virtual int est_cost() override;
virtual int compute_sharding_info() override;
virtual int compute_op_parallel_and_server_info() override;
inline const common::ObIArray<ObParamPosIdx> &get_param_infos() const { return param_infos_; }
inline const char *get_stmt_fmt_buf() const { return stmt_fmt_buf_; }
inline int32_t get_stmt_fmt_len() const { return stmt_fmt_len_; }

View File

@ -23,6 +23,7 @@
#include "common/ob_smart_call.h"
#include "sql/ob_optimizer_trace_impl.h"
#include "sql/engine/cmd/ob_table_direct_insert_service.h"
#include "sql/dblink/ob_dblink_utils.h"
using namespace oceanbase;
using namespace sql;
using namespace oceanbase::common;
@ -400,7 +401,7 @@ int ObOptimizer::check_pdml_enabled(const ObDMLStmt &stmt,
const ObSQLSessionInfo &session,
bool &is_use_pdml)
{
// https://yuque.antfin-inc.com/xiaochu.yh/doc/ii6elo
//
// 1. pdml: force parallel dml & no DISABLE_PARALLEL_DML hint
// 2. enable parallel query: parallel hint | sess enable_parallel_query
// pdml: enable parallel dml + enable parallel query
@ -481,6 +482,7 @@ int ObOptimizer::check_pdml_supported_feature(const ObDMLStmt &stmt,
const ObDelUpdStmt &pdml_stmt = static_cast<const ObDelUpdStmt &>(stmt);
ObSEArray<const ObDmlTableInfo*, 2> table_infos;
bool enable_all_pdml_feature = false; // 默认非注入错误情况下,关闭PDML不稳定feature
bool stmt_has_dblink = false;
// 目前通过注入错误的方式来打开PDML不稳定功能,用于PDML全部功能的case回归
// 对应的event注入任何类型的错误,都会打开PDML非稳定功能
ret = OB_E(EventTable::EN_ENABLE_PDML_ALL_FEATURE) OB_SUCCESS;
@ -511,6 +513,12 @@ int ObOptimizer::check_pdml_supported_feature(const ObDMLStmt &stmt,
static_cast< const ObInsertStmt &>(stmt).is_insert_up()) {
is_use_pdml = false;
ctx_.add_plan_note(PDML_DISABLED_BY_INSERT_UP);
} else if (OB_FAIL(ObDblinkUtils::has_reverse_link_or_any_dblink(&stmt, stmt_has_dblink, true))) {
LOG_WARN("failed to find dblink in stmt", K(ret));
} else if (stmt_has_dblink) {
is_use_pdml = false;
ctx_.add_plan_note(PARALLEL_DISABLED_BY_DBLINK);
ctx_.set_has_dblink(true);
} else if (ctx_.contain_user_nested_sql()) {
//user nested sql can't use PDML plan, force to use DAS plan
//if online ddl has pl udf, only this way, allow it use PDML plan
@ -615,6 +623,7 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt)
bool session_enable_parallel = false;
bool has_var_assign = false;
bool is_var_assign_only_in_root_stmt = false;
bool stmt_has_dblink = false;
uint64_t session_force_parallel_dop = 1;
int64_t max_table_dop = 1;
int64_t max_table_hint = 1;
@ -676,6 +685,12 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt)
ctx_.set_parallel(1);
ctx_.add_plan_note(PARALLEL_DISABLED_BY_PL_UDF_DAS, 1);
}
if (ctx_.has_dblink()) {
//if stmt contain dblink, force das, parallel should be 1
ctx_.set_parallel_rule(PXParallelRule::DBLINK_FORCE_SERIALIZE);
ctx_.set_parallel(1);
ctx_.add_plan_note(PARALLEL_DISABLED_BY_DBLINK, 1);
}
bool is_direct_insert = false;
if (OB_FAIL(ObTableDirectInsertService::check_direct_insert(ctx_, stmt, is_direct_insert))) {
LOG_WARN("failed to check direct insert", KR(ret));

View File

@ -227,7 +227,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
px_parallel_rule_ == MANUAL_TABLE_HINT ||
px_parallel_rule_ == SESSION_FORCE_PARALLEL ||
px_parallel_rule_ == MANUAL_TABLE_DOP ||
px_parallel_rule_ == PL_UDF_DAS_FORCE_SERIALIZE;
px_parallel_rule_ == PL_UDF_DAS_FORCE_SERIALIZE ||
px_parallel_rule_ == DBLINK_FORCE_SERIALIZE;
}
inline bool use_intra_parallel() const
{
@ -461,6 +462,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
bool has_trigger() const { return has_trigger_; }
void set_has_pl_udf(bool v) { has_pl_udf_ = v; }
bool has_pl_udf() const { return has_pl_udf_; }
void set_has_dblink(bool v) { has_dblink_ = v; }
bool has_dblink() const { return has_dblink_; }
void set_has_subquery_in_function_table(bool v) { has_subquery_in_function_table_ = v; }
bool has_subquery_in_function_table() const { return has_subquery_in_function_table_; }
bool contain_nested_sql() const { return nested_sql_flags_ > 0; }
@ -537,6 +540,7 @@ private:
int8_t has_trigger_ : 1; //this sql has trigger object
int8_t has_pl_udf_ : 1; //this sql has pl user defined function
int8_t has_subquery_in_function_table_ : 1; //this stmt has function table
int8_t has_dblink_ : 1; //this stmt has dblink table
};
};
bool has_for_update_;

View File

@ -132,7 +132,7 @@ int ObPxResourceAnalyzer::analyze(
// 2. 然后模拟调度,每调度一对 dfo,就将 child 设置为 done,然后统计当前时刻多少个未完成 dfo
// 3. 如此继续调度,直至所有 dfo 调度完成
//
// ref: https://yuque.antfin-inc.com/xiaochu.yh/doc/dlmg3w
// ref:
ObArray<PxInfo> px_trees;
if (OB_FAIL(convert_log_plan_to_nested_px_tree(px_trees, root_op))) {
LOG_WARN("fail convert log plan to nested px tree", K(ret));

View File

@ -304,7 +304,7 @@ do {
yyerror(NULL, result, "node or result is NULL\n"); \
YYABORT_UNEXPECTED; \
} else if (OB_UNLIKELY(!result->pl_parse_info_.is_pl_parse_ && 0 != result->question_mark_ctx_.count_)) { \
/* 如果是PL过来的sql语句,不要检查:
/* 如果是PL过来的sql语句,不要检查:*/ \
yyerror(NULL, result, "Unknown column '?'\n"); \
YYABORT_UNEXPECTED; \
} else { \

View File

@ -4406,7 +4406,7 @@ int ObTransformUtils::compute_table_property(const ObDMLStmt *stmt,
{
int ret = OB_SUCCESS;
const JoinedTable *joined_table = NULL;
if (OB_ISNULL(table)) {
if (OB_ISNULL(table) || OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected stmt", K(ret));
} else if (table->is_basic_table()
@ -4418,7 +4418,12 @@ int ObTransformUtils::compute_table_property(const ObDMLStmt *stmt,
cond_exprs, res_info)))) {
LOG_WARN("failed to compute generate table property", K(ret));
} else if (!table->is_joined_table()) {
/*do nothing*/
ObSqlBitSet<> rel_ids;
if (OB_FAIL(stmt->get_table_rel_ids(*table, rel_ids))) {
LOG_WARN("failed to get table ids", K(ret));
} else if (OB_FAIL(res_info.table_set_.add_members(rel_ids))) {
LOG_WARN("failed to add members", K(ret));
}
} else if (FALSE_IT(joined_table = static_cast<const JoinedTable *>(table))) {
} else if (joined_table->is_inner_join()) {
ret = SMART_CALL(compute_inner_join_property(stmt, check_helper, joined_table,

View File

@ -48,7 +48,7 @@ observer采用16位递增id表示当前server分配的sessid_seq。分配策略
#### session_key
为了解决ObServer在接收客户端断连接请求后,未能及时释放sessid的问题([详情](http://review.alibaba-inc.com/r/29086/)),引入了session_key的概念;
为了解决ObServer在接收客户端断连接请求后,未能及时释放sessid的问题,引入了session_key的概念;
- session_key为含有version和sessid两个成员变量的结构体,session_key作为ObSQLSessionInfo在session map中的key;通过session_key对ObSQLSessioInfo进行create_session/get_session/free_session;
- 当ObServer接收到断连接请求后,在on_disconnect接口中,对sessid 进行unused,并将相应的ObSQLSessionInfo设置为shadow
- 如果proxy采取saved_login,并使用相同的sessid,observer如果判断出当前full_sessid对应的ObSQLSessionInfo为shadow,则会创建一个新的ObSQLSessionInfo,并指定一个可用的version。

View File

@ -268,7 +268,7 @@ private:
//ObNullEndTransCallback null_callback_;
// used for manage ObSQLSessionInfo
HashMap sessinfo_map_;
// design doc: https://yuque.antfin-inc.com/docs/share/820fa006-f85a-4530-8e2b-fe3c90271404
// design doc:
// |<---------------------------------32bit---------------------------->|
// 31b 30b 29b 18b 16b 0b
// +----+------------------------------+--------------------------------+

View File

@ -303,6 +303,54 @@ int ObDirectLoadTabletMergeCtx::collect_sql_statistics(
return ret;
}
int ObDirectLoadTabletMergeCtx::init_sstable_array(
const ObIArray<ObIDirectLoadPartitionTable *> &table_array)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) {
ObDirectLoadSSTable *sstable = nullptr;
if (OB_ISNULL(sstable = dynamic_cast<ObDirectLoadSSTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(sstable_array_.push_back(sstable))) {
LOG_WARN("fail to push back sstable", KR(ret));
}
}
return ret;
}
int ObDirectLoadTabletMergeCtx::init_multiple_sstable_array(
const ObIArray<ObIDirectLoadPartitionTable *> &table_array)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) {
ObDirectLoadMultipleSSTable *sstable = nullptr;
if (OB_ISNULL(sstable = dynamic_cast<ObDirectLoadMultipleSSTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(multiple_sstable_array_.push_back(sstable))) {
LOG_WARN("fail to push back multiple sstable", KR(ret));
}
}
return ret;
}
int ObDirectLoadTabletMergeCtx::init_multiple_heap_table_array(
const ObIArray<ObIDirectLoadPartitionTable *> &table_array)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) {
ObDirectLoadMultipleHeapTable *heap_table = nullptr;
if (OB_ISNULL(heap_table = dynamic_cast<ObDirectLoadMultipleHeapTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(multiple_heap_table_array_.push_back(heap_table))) {
LOG_WARN("fail to push back multiple heap table", KR(ret));
}
}
return ret;
}
int ObDirectLoadTabletMergeCtx::build_merge_task(
const ObIArray<ObIDirectLoadPartitionTable *> &table_array,
const ObIArray<ObColDesc> &col_descs,
@ -393,16 +441,10 @@ int ObDirectLoadTabletMergeCtx::build_pk_table_merge_task(
int64_t max_parallel_degree)
{
int ret = OB_SUCCESS;
// split range
for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) {
ObDirectLoadSSTable *sstable = nullptr;
if (OB_ISNULL(sstable = dynamic_cast<ObDirectLoadSSTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(sstable_array_.push_back(sstable))) {
LOG_WARN("fail to push back sstable", KR(ret));
}
if (OB_FAIL(init_sstable_array(table_array))) {
LOG_WARN("fail to init sstable array", KR(ret));
}
// split range
if (OB_SUCC(ret)) {
ObDirectLoadMergeRangeSplitter range_splitter;
if (OB_FAIL(
@ -444,16 +486,10 @@ int ObDirectLoadTabletMergeCtx::build_pk_table_multiple_merge_task(
int64_t max_parallel_degree)
{
int ret = OB_SUCCESS;
// split range
for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) {
ObDirectLoadMultipleSSTable *sstable = nullptr;
if (OB_ISNULL(sstable = dynamic_cast<ObDirectLoadMultipleSSTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(multiple_sstable_array_.push_back(sstable))) {
LOG_WARN("fail to push back sstable", KR(ret));
}
if (OB_FAIL(init_multiple_sstable_array(table_array))) {
LOG_WARN("fail to init multiple sstable array", KR(ret));
}
// split range
if (OB_SUCC(ret)) {
ObDirectLoadMultipleMergeTabletRangeSplitter range_splitter;
if (OB_FAIL(range_splitter.init(tablet_id_, &origin_table_, multiple_sstable_array_,
@ -617,6 +653,9 @@ int ObDirectLoadTabletMergeCtx::build_heap_table_multiple_merge_task(
{
int ret = OB_SUCCESS;
int64_t parallel_idx = 0;
if (OB_FAIL(init_multiple_heap_table_array(table_array))) {
LOG_WARN("fail to init multiple heap table array", KR(ret));
}
// for existing data, construct task by split range
if (OB_SUCC(ret)) {
ObDirectLoadMergeRangeSplitter range_splitter;
@ -651,16 +690,12 @@ int ObDirectLoadTabletMergeCtx::build_heap_table_multiple_merge_task(
}
}
// for imported data, construct task by multiple heap table
for (int64_t i = 0; OB_SUCC(ret) && !param_.is_fast_heap_table_ && i < table_array.count(); ++i) {
ObDirectLoadMultipleHeapTable *heap_table = nullptr;
for (int64_t i = 0; OB_SUCC(ret) && !param_.is_fast_heap_table_ && i < multiple_heap_table_array_.count(); ++i) {
ObDirectLoadMultipleHeapTable *heap_table = multiple_heap_table_array_.at(i);
ObDirectLoadPartitionHeapTableMultipleMergeTask *merge_task = nullptr;
int64_t row_count = 0;
ObTabletCacheInterval pk_interval;
if (OB_ISNULL(heap_table = dynamic_cast<ObDirectLoadMultipleHeapTable *>(table_array.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table", KR(ret), K(i), K(table_array));
} else if (OB_FAIL(heap_table->get_tablet_row_count(tablet_id_, param_.table_data_desc_,
row_count))) {
if (OB_FAIL(heap_table->get_tablet_row_count(tablet_id_, param_.table_data_desc_, row_count))) {
LOG_WARN("fail to get tablet row count", KR(ret), K(tablet_id_));
} else if (0 == row_count) {
// ignore
@ -686,6 +721,50 @@ int ObDirectLoadTabletMergeCtx::build_heap_table_multiple_merge_task(
return ret;
}
int ObDirectLoadTabletMergeCtx::build_aggregate_merge_task_for_multiple_heap_table(
const ObIArray<ObIDirectLoadPartitionTable *> &table_array)
{
int ret = OB_SUCCESS;
int64_t total_row_count = 0;
ObTabletCacheInterval pk_interval;
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask *merge_task = nullptr;
if (OB_FAIL(init_multiple_heap_table_array(table_array))) {
LOG_WARN("fail to init multiple heap table array", KR(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < multiple_heap_table_array_.count(); ++i) {
ObDirectLoadMultipleHeapTable *heap_table = multiple_heap_table_array_.at(i);
int64_t row_count = 0;
if (OB_FAIL(heap_table->get_tablet_row_count(tablet_id_, param_.table_data_desc_, row_count))) {
LOG_WARN("fail to get tablet row count", KR(ret), K(tablet_id_));
} else {
total_row_count += row_count;
}
}
if (OB_SUCC(ret)) {
if (total_row_count > 0 && OB_FAIL(get_autoincrement_value(total_row_count, pk_interval))) {
LOG_WARN("fail to get autoincrement value", KR(ret), K(total_row_count));
} else if (OB_ISNULL(merge_task =
OB_NEWx(ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask,
(&allocator_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to new ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask", KR(ret));
} else if (OB_FAIL(merge_task->init(param_, this, &origin_table_, multiple_heap_table_array_,
pk_interval))) {
LOG_WARN("fail to init merge task", KR(ret));
} else if (OB_FAIL(task_array_.push_back(merge_task))) {
LOG_WARN("fail to push back merge task", KR(ret));
}
}
if (OB_FAIL(ret)) {
if (nullptr != merge_task) {
merge_task->~ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask();
allocator_.free(merge_task);
merge_task = nullptr;
}
}
return ret;
}
int ObDirectLoadTabletMergeCtx::get_autoincrement_value(uint64_t count,
ObTabletCacheInterval &interval)
{

View File

@ -34,6 +34,7 @@ class ObDirectLoadTabletMergeCtx;
class ObIDirectLoadPartitionTable;
class ObDirectLoadSSTable;
class ObDirectLoadMultipleSSTable;
class ObDirectLoadMultipleHeapTable;
class ObDirectLoadMultipleMergeRangeSplitter;
struct ObDirectLoadMergeParam
@ -99,6 +100,8 @@ public:
const common::ObIArray<ObDirectLoadMultipleSSTable *> &multiple_sstable_array,
ObDirectLoadMultipleMergeRangeSplitter &range_splitter,
int64_t max_parallel_degree);
int build_aggregate_merge_task_for_multiple_heap_table(
const common::ObIArray<ObIDirectLoadPartitionTable *> &table_array);
int inc_finish_count(bool &is_ready);
int collect_sql_statistics(
const common::ObIArray<ObDirectLoadFastHeapTable *> &fast_heap_table_array, table::ObTableLoadSqlStatistics &sql_statistics);
@ -111,6 +114,11 @@ public:
}
TO_STRING_KV(K_(param), K_(target_partition_id), K_(tablet_id), K_(target_tablet_id));
private:
int init_sstable_array(const common::ObIArray<ObIDirectLoadPartitionTable *> &table_array);
int init_multiple_sstable_array(
const common::ObIArray<ObIDirectLoadPartitionTable *> &table_array);
int init_multiple_heap_table_array(
const common::ObIArray<ObIDirectLoadPartitionTable *> &table_array);
int build_empty_data_merge_task(const common::ObIArray<share::schema::ObColDesc> &col_descs,
int64_t max_parallel_degree);
int build_pk_table_merge_task(const common::ObIArray<ObIDirectLoadPartitionTable *> &table_array,
@ -138,6 +146,7 @@ private:
ObDirectLoadOriginTable origin_table_;
common::ObSEArray<ObDirectLoadSSTable *, 64> sstable_array_;
common::ObSEArray<ObDirectLoadMultipleSSTable *, 64> multiple_sstable_array_;
common::ObSEArray<ObDirectLoadMultipleHeapTable *, 64> multiple_heap_table_array_;
common::ObSEArray<blocksstable::ObDatumRange, 64> range_array_;
common::ObSEArray<ObDirectLoadPartitionMergeTask *, 64> task_array_;
int64_t task_finish_count_ CACHE_ALIGNED;

View File

@ -5,13 +5,14 @@
#define USING_LOG_PREFIX STORAGE
#include "storage/direct_load/ob_direct_load_partition_merge_task.h"
#include "share/stat/ob_opt_column_stat.h"
#include "share/stat/ob_stat_define.h"
#include "storage/ddl/ob_direct_insert_sstable_ctx.h"
#include "storage/direct_load/ob_direct_load_external_table.h"
#include "storage/direct_load/ob_direct_load_insert_table_ctx.h"
#include "storage/direct_load/ob_direct_load_multiple_heap_table.h"
#include "storage/direct_load/ob_direct_load_merge_ctx.h"
#include "share/stat/ob_opt_column_stat.h"
#include "share/stat/ob_stat_define.h"
#include "storage/direct_load/ob_direct_load_multiple_heap_table.h"
#include "storage/direct_load/ob_direct_load_origin_table.h"
namespace oceanbase
{
@ -822,5 +823,233 @@ int ObDirectLoadPartitionHeapTableMultipleMergeTask::construct_row_iter(
return ret;
}
/**
* ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask
*/
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::RowIterator()
: origin_iter_(nullptr),
rowkey_column_num_(0),
store_column_count_(0),
heap_table_array_(nullptr),
pos_(0),
deserialize_datums_(nullptr),
deserialize_datum_cnt_(0),
result_info_(nullptr),
is_inited_(false)
{
}
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::~RowIterator()
{
}
int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::init(
const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id,
ObDirectLoadOriginTable *origin_table,
const ObIArray<ObDirectLoadMultipleHeapTable *> *heap_table_array,
const ObTabletCacheInterval &pk_interval)
{
int ret = OB_SUCCESS;
if (IS_INIT) {
ret = OB_INIT_TWICE;
LOG_WARN("ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator init twice", KR(ret),
KP(this));
} else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() ||
nullptr == origin_table || nullptr == heap_table_array)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), KP(origin_table),
KP(heap_table_array));
} else {
range_.set_whole_range();
if (OB_FAIL(origin_table->scan(range_, allocator_, origin_iter_))) {
LOG_WARN("fail to scan origin table", KR(ret));
}
// init datum_row_
else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ +
ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) {
LOG_WARN("fail to init datum row", KR(ret));
} else {
datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT);
datum_row_.mvcc_row_flag_.set_last_multi_version_row(true);
datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int(
-merge_param.snapshot_version_); // fill trans_version
datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no
deserialize_datums_ = datum_row_.storage_datums_ + merge_param.rowkey_column_num_ +
ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt();
deserialize_datum_cnt_ = merge_param.store_column_count_ - merge_param.rowkey_column_num_;
rowkey_column_num_ = merge_param.rowkey_column_num_;
store_column_count_ = merge_param.store_column_count_;
tablet_id_ = tablet_id;
table_data_desc_ = merge_param.table_data_desc_;
heap_table_array_ = heap_table_array;
pk_interval_ = pk_interval;
result_info_ = merge_param.result_info_;
is_inited_ = true;
}
}
return ret;
}
int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::get_next_row(
const ObDatumRow *&result_row)
{
int ret = OB_SUCCESS;
result_row = nullptr;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
LOG_WARN("ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator not init",
KR(ret), KP(this));
} else {
if (pos_ == 0) {
const ObDatumRow *datum_row = nullptr;
if (OB_FAIL(origin_iter_->get_next_row(datum_row))) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("fail to get next row", KR(ret));
} else {
// switch heap table
ret = OB_SUCCESS;
if (OB_FAIL(switch_next_heap_table())) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("fail to switch next heap table", KR(ret));
}
}
}
} else if (OB_UNLIKELY(datum_row->count_ != store_column_count_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected column count", KR(ret), K(store_column_count_), KPC(datum_row));
} else {
// copy rowkey columns
for (int64_t i = 0; i < rowkey_column_num_; ++i) {
datum_row_.storage_datums_[i] = datum_row->storage_datums_[i];
}
// copy normal columns
for (int64_t
i = rowkey_column_num_,
j = rowkey_column_num_ + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt();
i < datum_row->count_; ++i, ++j) {
datum_row_.storage_datums_[j] = datum_row->storage_datums_[i];
}
result_row = &datum_row_;
}
}
while (OB_SUCC(ret) && result_row == nullptr) {
const ObDirectLoadMultipleExternalRow *external_row = nullptr;
uint64_t pk_seq = OB_INVALID_ID;
if (OB_FAIL(scanner_.get_next_row(external_row))) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("fail to get next row", KR(ret));
} else {
// switch next heap table
ret = OB_SUCCESS;
if (OB_FAIL(switch_next_heap_table())) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("fail to switch next heap table", KR(ret));
}
}
}
} else if (OB_FAIL(external_row->to_datums(deserialize_datums_, deserialize_datum_cnt_))) {
LOG_WARN("fail to transfer datum row", KR(ret));
} else if (OB_FAIL(pk_interval_.next_value(pk_seq))) {
LOG_WARN("fail to get next pk seq", KR(ret));
} else {
// fill hide pk
datum_row_.storage_datums_[0].set_int(pk_seq);
result_row = &datum_row_;
ATOMIC_INC(&result_info_->rows_affected_);
}
}
}
return ret;
}
int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::switch_next_heap_table()
{
int ret = OB_SUCCESS;
if (pos_ >= heap_table_array_->count()) {
ret = OB_ITER_END;
} else {
ObDirectLoadMultipleHeapTable *heap_table = heap_table_array_->at(pos_);
// restructure scanner
scanner_.~ObDirectLoadMultipleHeapTableTabletWholeScanner();
new (&scanner_) ObDirectLoadMultipleHeapTableTabletWholeScanner();
if (OB_FAIL(scanner_.init(heap_table, tablet_id_, table_data_desc_))) {
LOG_WARN("fail to init scanner", KR(ret));
} else {
++pos_;
}
}
return ret;
}
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask()
: origin_table_(nullptr), heap_table_array_(nullptr)
{
}
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::
~ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask()
{
}
int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::init(
const ObDirectLoadMergeParam &merge_param, ObDirectLoadTabletMergeCtx *merge_ctx,
ObDirectLoadOriginTable *origin_table,
const ObIArray<ObDirectLoadMultipleHeapTable *> &heap_table_array,
const ObTabletCacheInterval &pk_interval)
{
int ret = OB_SUCCESS;
if (IS_INIT) {
ret = OB_INIT_TWICE;
LOG_WARN("ObDirectLoadPartitionHeapTableMultipleMergeTask init twice", KR(ret), KP(this));
} else if (OB_UNLIKELY(!merge_param.is_valid() || nullptr == merge_ctx ||
nullptr == origin_table || heap_table_array.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", KR(ret), K(merge_param), KP(merge_ctx), KP(origin_table),
K(heap_table_array));
} else {
merge_param_ = &merge_param;
merge_ctx_ = merge_ctx;
parallel_idx_ = 0;
origin_table_ = origin_table;
heap_table_array_ = &heap_table_array;
pk_interval_ = pk_interval;
is_inited_ = true;
}
return ret;
}
int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::construct_row_iter(
ObIAllocator &allocator, ObIStoreRowIterator *&result_row_iter)
{
int ret = OB_SUCCESS;
result_row_iter = nullptr;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
LOG_WARN("ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask not init", KR(ret),
KP(this));
} else {
RowIterator *row_iter = nullptr;
if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to new RowIterator", KR(ret));
} else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_,
heap_table_array_, pk_interval_))) {
LOG_WARN("fail to init row iter", KR(ret));
} else {
result_row_iter = row_iter;
}
if (OB_FAIL(ret)) {
if (nullptr != row_iter) {
row_iter->~RowIterator();
allocator.free(row_iter);
row_iter = nullptr;
}
}
}
return ret;
}
} // namespace storage
} // namespace oceanbase

View File

@ -206,5 +206,56 @@ private:
share::ObTabletCacheInterval pk_interval_;
};
class ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask
: public ObDirectLoadPartitionMergeTask
{
public:
ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask();
virtual ~ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask();
int init(const ObDirectLoadMergeParam &merge_param, ObDirectLoadTabletMergeCtx *merge_ctx,
ObDirectLoadOriginTable *origin_table,
const common::ObIArray<ObDirectLoadMultipleHeapTable *> &heap_table_array,
const share::ObTabletCacheInterval &pk_interval);
protected:
int construct_row_iter(common::ObIAllocator &allocator, ObIStoreRowIterator *&row_iter) override;
private:
class RowIterator : public ObIStoreRowIterator
{
public:
RowIterator();
virtual ~RowIterator();
int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id,
ObDirectLoadOriginTable *origin_table,
const common::ObIArray<ObDirectLoadMultipleHeapTable *> *heap_table_array,
const share::ObTabletCacheInterval &pk_interval);
int get_next_row(const blocksstable::ObDatumRow *&datum_row) override;
private:
int switch_next_heap_table();
private:
// for iter origin table
common::ObArenaAllocator allocator_;
blocksstable::ObDatumRange range_;
ObIStoreRowIterator *origin_iter_;
int64_t rowkey_column_num_;
int64_t store_column_count_;
// for iter multiple heap table
common::ObTabletID tablet_id_;
ObDirectLoadTableDataDesc table_data_desc_;
const common::ObIArray<ObDirectLoadMultipleHeapTable *> *heap_table_array_;
int64_t pos_;
ObDirectLoadMultipleHeapTableTabletWholeScanner scanner_;
blocksstable::ObDatumRow datum_row_;
blocksstable::ObStorageDatum *deserialize_datums_;
int64_t deserialize_datum_cnt_;
share::ObTabletCacheInterval pk_interval_;
table::ObTableLoadResultInfo *result_info_;
bool is_inited_;
};
private:
ObDirectLoadOriginTable *origin_table_;
const common::ObIArray<ObDirectLoadMultipleHeapTable *> *heap_table_array_;
share::ObTabletCacheInterval pk_interval_;
};
} // namespace storage
} // namespace oceanbase

View File

@ -237,9 +237,23 @@ public:
void clear_pending_log_size() { ATOMIC_STORE(&pending_log_size_, 0); }
int64_t get_pending_log_size() { return ATOMIC_LOAD(&pending_log_size_); }
int64_t get_flushed_log_size() { return ATOMIC_LOAD(&flushed_log_size_); }
bool is_all_redo_submitted(ObITransCallback *generate_cursor)
bool is_all_redo_submitted()
{
return (ObITransCallback *)callback_list_.get_tail() == generate_cursor;
bool all_redo_submitted = true;
if (OB_NOT_NULL(callback_lists_)) {
for (int64_t i = 0; i < MAX_CALLBACK_LIST_COUNT; ++i) {
if (!callback_lists_[i].empty()) {
all_redo_submitted = false;
break;
}
}
}
if (all_redo_submitted) {
all_redo_submitted = !(((ObITransCallback *)callback_list_.get_tail())->need_submit_log());
}
return all_redo_submitted;
}
void merge_multi_callback_lists();
void reset_pdml_stat();
@ -278,10 +292,6 @@ public:
share::SCN get_checksum_scn() const { return callback_list_.get_checksum_scn(); }
transaction::ObPartTransCtx *get_trans_ctx() const;
private:
bool is_all_redo_submitted(ObMvccRowCallback *generate_cursor)
{
return (ObMvccRowCallback *)callback_list_.get_tail() == generate_cursor;
}
void force_merge_multi_callback_lists();
private:
ObITransCallback *get_guard_() { return callback_list_.get_guard(); }

View File

@ -223,10 +223,10 @@ void ObMemtableCtx::dec_ref()
(void)ATOMIC_AAF(&ref_, -1);
}
void ObMemtableCtx::set_replay()
void ObMemtableCtx::wait_pending_write()
{
WRLockGuard guard(rwlock_);
is_master_ = false;
ATOMIC_STORE(&is_master_, false);
WRLockGuard wrguard(rwlock_);
}
SCN ObMemtableCtx::get_tx_end_scn() const
@ -907,10 +907,9 @@ int ObMemtableCtx::rollback(const int64_t to_seq_no, const int64_t from_seq_no)
bool ObMemtableCtx::is_all_redo_submitted()
{
ObByteLockGuard guard(lock_);
return trans_mgr_.is_all_redo_submitted(log_gen_.get_generate_cursor());
return trans_mgr_.is_all_redo_submitted();
}
int ObMemtableCtx::remove_callbacks_for_fast_commit()
{
int ret = OB_SUCCESS;

View File

@ -342,7 +342,7 @@ public:
virtual void set_read_only();
virtual void inc_ref();
virtual void dec_ref();
void set_replay();
void wait_pending_write();
virtual int write_auth(const bool exclusive);
virtual int write_done();
virtual int trans_begin();

View File

@ -1722,6 +1722,7 @@ enum class TxEndAction : int8_t
{
COMMIT_TX,
ABORT_TX,
DELAY_ABORT_TX,
KILL_TX_FORCEDLY
};

View File

@ -971,6 +971,16 @@ bool ObPartTransCtx::is_in_2pc_() const
bool ObPartTransCtx::is_logging_() const { return !busy_cbs_.is_empty(); }
bool ObPartTransCtx::need_force_abort_() const
{
return sub_state_.is_force_abort() && !sub_state_.is_state_log_submitted();
}
bool ObPartTransCtx::is_force_abort_logging_() const
{
return sub_state_.is_force_abort() && sub_state_.is_state_log_submitting();
}
bool ObPartTransCtx::has_persisted_log_() const
{
return exec_info_.max_applying_log_ts_.is_valid();
@ -1244,6 +1254,9 @@ int ObPartTransCtx::check_rs_scheduler_is_alive_(bool &is_alive)
if (OB_ISNULL(trans_service_)) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(WARN, "trans service is NULL", KR(ret), K(*this));
} else if (need_force_abort_() && !exec_info_.scheduler_.is_valid()) {
is_alive = false;
TRANS_LOG(WARN, "a aborting trans will be gc with invalid scheduler", K(ret), K(is_alive), KPC(this));
} else if (OB_ISNULL(server_tracer = trans_service_->get_server_tracer())) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(WARN, "server tracer is NULL", KR(ret), K(*this));
@ -1304,6 +1317,10 @@ int ObPartTransCtx::check_scheduler_status()
}
// 2. Ask for the status of scheduler
ret = OB_SUCCESS;
int ctx_status = OB_SUCCESS;
if (sub_state_.is_force_abort()) {
ctx_status = OB_TRANS_KILLED;
}
if (is_alive && need_check_scheduler) {
ObTxKeepaliveMsg msg;
msg.cluster_version_ = cluster_version_;
@ -1315,7 +1332,7 @@ int ObPartTransCtx::check_scheduler_status()
msg.sender_ = ls_id_;
msg.receiver_ = share::SCHEDULER_LS; // this just used to pass validation
msg.epoch_ = epoch_;
msg.status_ = OB_SUCCESS;
msg.status_ = ctx_status;
if (OB_FAIL(rpc_->post_msg(exec_info_.scheduler_, msg))) {
TRANS_LOG(WARN, "post tx keepalive msg fail", K(ret), K(msg), KPC(this));
}
@ -1567,7 +1584,7 @@ int ObPartTransCtx::check_and_submit_redo_log_(bool &try_submit)
bool is_tx_committing = ObTxState::INIT != get_downstream_state();
bool final_log_submitting = final_log_cb_.is_valid();
if (!is_tx_committing && !final_log_submitting) {
if (!is_tx_committing && !final_log_submitting && !is_force_abort_logging_()) {
(void)mt_ctx_.merge_multi_callback_lists_for_immediate_logging();
ret = submit_log_impl_(ObTxLogType::TX_REDO_LOG);
try_submit = true;
@ -1636,7 +1653,9 @@ bool ObPartTransCtx::is_table_lock_killed() const
int ObPartTransCtx::compensate_abort_log_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(submit_log_impl_(ObTxLogType::TX_ABORT_LOG))) {
if (is_force_abort_logging_()) {
// do nothing
} else if (OB_FAIL(submit_log_impl_(ObTxLogType::TX_ABORT_LOG))) {
TRANS_LOG(WARN, "submit abort log failed", KR(ret), K(*this));
} else {
sub_state_.set_force_abort();
@ -2045,7 +2064,7 @@ int ObPartTransCtx::try_submit_next_log_(const bool for_freeze)
int ret = OB_SUCCESS;
ObTxLogType log_type = ObTxLogType::UNKNOWN;
if (ObPartTransAction::COMMIT == part_trans_action_ && !is_2pc_logging_() && !is_in_2pc_()
&& !sub_state_.is_force_abort()) {
&& !need_force_abort_()) {
if (is_follower_()) {
ret = OB_NOT_MASTER;
} else {
@ -2306,6 +2325,43 @@ int ObPartTransCtx::fill_redo_log_(char *buf,
int ret = OB_SUCCESS;
const bool log_for_lock_node = true;
// const bool log_for_lock_node = !(is_local_tx_() && (part_trans_action_ == ObPartTransAction::COMMIT));
// // // //
// Possible problems caused:
// 1. block frozen : We wiil not add data_node_count if skip lock node in fill_redo. Then the next memtable
// will return -4112 and the prev memtable will wait for lock node clearing unsubmitted_cnt.
// 2. replay checksum error:
// |
// | part_trans_action != COMMIT
// v
// +-------------------------------------+
// | start submit_commit_log |
// +-------------------------------------+
// |
// |
// v
// +-------------------------------------+
// | log_for_lock_node == false |
// | cal checksum with lock node |
// +-------------------------------------+
// |
// |
// v
// +-------------------------------------+
// | submit commit log failed with -4038 |
// | rewrite as OB_SUCCESS |
// +-------------------------------------+
// |
// | part_trans_action = COMMIT
// v
// +-------------------------------------+
// | retry submit commit log |
// +-------------------------------------+
// |
// |
// v
// +-------------------------------------+
// | replay checksum ERROR |
// +-------------------------------------+
if (OB_UNLIKELY(NULL == buf || buf_len < 0 || pos < 0 || buf_len < pos)) {
ret = OB_INVALID_ARGUMENT;
@ -2446,7 +2502,7 @@ int ObPartTransCtx::submit_redo_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObRedoLogSubmitHelper helper;
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
@ -2495,7 +2551,7 @@ int ObPartTransCtx::submit_redo_commit_info_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObRedoLogSubmitHelper helper;
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (sub_state_.is_info_log_submitted()) {
// state log already submitted, do nothing
@ -2619,7 +2675,7 @@ int ObPartTransCtx::submit_redo_active_info_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObRedoLogSubmitHelper helper;
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
@ -2728,7 +2784,7 @@ int ObPartTransCtx::submit_prepare_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObRedoLogSubmitHelper helper;
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
@ -2849,7 +2905,8 @@ int ObPartTransCtx::submit_commit_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObRedoLogSubmitHelper helper;
ObTxBufferNodeArray multi_source_data;
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
const bool local_tx = is_local_tx_();
if (OB_FAIL(gen_final_mds_array_(multi_source_data))) {
@ -2870,7 +2927,10 @@ int ObPartTransCtx::submit_commit_log_()
} else if (use_local_block_buf) {
// realloc log buf and retry submit log
log_block.reset();
ObTxLogBlockHeader tmp_log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader tmp_log_block_header(cluster_id_,
exec_info_.next_log_entry_no_,
trans_id_,
exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, tmp_log_block_header, false /*use_local_block_buf*/))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
} else if (OB_FAIL(submit_redo_commit_info_log_(log_block, has_redo, helper))) {
@ -3049,7 +3109,7 @@ int ObPartTransCtx::submit_abort_log_()
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(gen_final_mds_array_(tmp_array, false))) {
TRANS_LOG(WARN, "gen abort mds array failed", K(ret));
@ -3108,7 +3168,8 @@ int ObPartTransCtx::submit_clear_log_()
ObTxClearLog clear_log(exec_info_.incremental_participants_);
ObTxLogCb *log_cb = NULL;
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
@ -3152,7 +3213,7 @@ int ObPartTransCtx::submit_record_log_()
ObTxLogCb *log_cb = NULL;
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
@ -3206,7 +3267,7 @@ int ObPartTransCtx::submit_big_segment_log_()
while (OB_SUCC(ret)) {
const char *submit_buf = nullptr;
int64_t submit_buf_len = 0;
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
} else if (OB_FAIL(prepare_log_cb_(!NEED_FINAL_CB, log_cb))) {
@ -3551,7 +3612,7 @@ int ObPartTransCtx::after_submit_log_(ObTxLogBlock &log_block,
exec_info_.next_log_entry_no_++;
ObTxLogBlockHeader
block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
log_block.reuse(trans_id_, block_header);
return ret;
}
@ -4894,7 +4955,7 @@ int ObPartTransCtx::switch_to_leader(const SCN &start_working_ts)
} else {
TRANS_LOG(WARN, "txn data incomplete, will be aborted", K(contain_table_lock), KPC(this));
if (has_persisted_log_()) {
if (OB_FAIL(do_local_tx_end_(TxEndAction::ABORT_TX))) {
if (OB_FAIL(do_local_tx_end_(TxEndAction::DELAY_ABORT_TX))) {
TRANS_LOG(WARN, "abort tx failed", KR(ret), K(*this));
}
} else {
@ -5014,12 +5075,14 @@ int ObPartTransCtx::switch_to_follower_forcedly(ObIArray<ObTxCommitCallback> &cb
TRANS_LOG(INFO, "switch to follower forcely, txn aborted without persisted log", KPC(this));
} else {
// has persisted log, wait new leader to advance it
if (OB_FAIL(mt_ctx_.commit_to_replay())) {
TRANS_LOG(WARN, "commit to replay error", KR(ret), "context", *this);
} else if (OB_FAIL(mt_ctx_.clean_unlog_callbacks())) {
if (pending_write_ && OB_FALSE_IT(mt_ctx_.wait_pending_write())) {
// do nothing
} else if (OB_FALSE_IT(mt_ctx_.commit_to_replay())) {
// do nothing
} else if (OB_FALSE_IT(mt_ctx_.merge_multi_callback_lists_for_changing_leader())) {
// do nothing
} else if (!mt_ctx_.is_all_redo_submitted() && OB_FAIL(mt_ctx_.clean_unlog_callbacks())) {
TRANS_LOG(WARN, "clear unlog callbacks", KR(ret), K(*this));
} else {
TRANS_LOG(DEBUG, "commit to replay success", "context", *this);
}
// special handle commit triggered by local call: coordinator colocate with scheduler
@ -5071,7 +5134,7 @@ int ObPartTransCtx::switch_to_follower_gracefully(ObIArray<ObTxCommitCallback> &
TRANS_LOG(ERROR, "tenant not match", K(ret), K(*this));
} else if (is_exiting_) {
// do nothing
} else if (sub_state_.is_force_abort()) {
} else if (is_force_abort_logging_()) {
// is aborting, skip
} else if (is_follower_()) {
TRANS_LOG(INFO, "current tx already follower", K(*this));
@ -5080,7 +5143,7 @@ int ObPartTransCtx::switch_to_follower_gracefully(ObIArray<ObTxCommitCallback> &
} else {
if (pending_write_) {
TRANS_LOG(INFO, "current tx is executing stmt", K(*this));
mt_ctx_.set_replay();
mt_ctx_.wait_pending_write();
need_submit_log = true;
} else if (!is_committing_()) {
need_submit_log = true;
@ -5109,7 +5172,7 @@ int ObPartTransCtx::switch_to_follower_gracefully(ObIArray<ObTxCommitCallback> &
}
}
timeguard.click();
if (OB_SUCC(ret) && need_submit_log) {
if (OB_SUCC(ret) && need_submit_log && !need_force_abort_()) {
// We need merge all callbacklists before submitting active info
(void)mt_ctx_.merge_multi_callback_lists_for_changing_leader();
if (ObTxLogType::TX_COMMIT_INFO_LOG == log_type) {
@ -5532,8 +5595,8 @@ int ObPartTransCtx::submit_multi_data_source_()
int ret = OB_SUCCESS;
ObTxLogBlock log_block;
const int64_t replay_hint = static_cast<int64_t>(trans_id_.get_id());
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_,
exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block failed", KR(ret), K(*this));
} else {
@ -5693,6 +5756,7 @@ int ObPartTransCtx::register_multi_data_source(const ObTxDataSourceType data_sou
ObString data;
void *ptr = nullptr;
ObTxBufferNodeArray tmp_array;
bool need_lock = true;
if (try_lock) {
@ -5704,6 +5768,7 @@ int ObPartTransCtx::register_multi_data_source(const ObTxDataSourceType data_sou
} else {
// do nothing
}
if (OB_SUCC(ret)) {
CtxLockGuard guard(lock_, need_lock);
@ -5711,12 +5776,23 @@ int ObPartTransCtx::register_multi_data_source(const ObTxDataSourceType data_sou
|| data_source_type >= ObTxDataSourceType::MAX_TYPE)) {
ret = OB_INVALID_ARGUMENT;
TRANS_LOG(WARN, "invalid argument", KR(ret), K(data_source_type), KP(buf), K(len));
} else if (OB_UNLIKELY(is_committing_())) {
ret = OB_TRANS_HAS_DECIDED;
if (is_trans_expired_() && ObPartTransAction::ABORT == part_trans_action_) {
// rewrite error with TRANS_TIMEOUT to easy user
ret = OB_TRANS_TIMEOUT;
} else if (ObPartTransAction::ABORT == part_trans_action_
|| exec_info_.state_ == ObTxState::ABORT) {
ret = OB_TRANS_KILLED;
}
TRANS_LOG(WARN, "tx has decided", K(ret), KPC(this));
} else if (OB_UNLIKELY(sub_state_.is_force_abort())) {
ret = OB_TRANS_KILLED;
TRANS_LOG(WARN, "tx force aborted due to data incomplete", K(ret), KPC(this));
} else if (is_follower_()) {
ret = OB_NOT_MASTER;
TRANS_LOG(WARN, "can not register mds on a follower", K(ret), K(data_source_type), K(len), KPC(this));
} else if (is_committing_()) {
ret = OB_TRANS_HAS_DECIDED;
TRANS_LOG(WARN, "can not register mds in committing part_ctx", K(ret), KPC(this));
TRANS_LOG(WARN, "can not register mds on a follower", K(ret), K(data_source_type), K(len),
KPC(this));
} else if (OB_ISNULL(ptr = mtl_malloc(len, "MultiTxData"))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
TRANS_LOG(WARN, "allocate memory failed", KR(ret), K(data_source_type), K(len));
@ -5731,13 +5807,13 @@ int ObPartTransCtx::register_multi_data_source(const ObTxDataSourceType data_sou
ret = OB_INVALID_ARGUMENT;
TRANS_LOG(WARN, "too large mds buf node", K(ret), K(tmp_array.get_serialize_size()));
} else if (OB_FAIL(mds_cache_.insert_mds_node(node))) {
TRANS_LOG(WARN, "register multi source data failed", KR(ret), K(data_source_type), K(*this));
TRANS_LOG(WARN, "register multi source data failed", KR(ret), K(data_source_type),
K(*this));
}
if (OB_FAIL(ret)) {
mtl_free(ptr);
} else if (OB_FAIL(notify_data_source_(NotifyType::REGISTER_SUCC, SCN(), false,
tmp_array))) {
} else if (OB_FAIL(notify_data_source_(NotifyType::REGISTER_SUCC, SCN(), false, tmp_array))) {
if (OB_SUCCESS != (tmp_ret = mds_cache_.rollback_last_mds_node())) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(ERROR, "rollback last mds node failed", K(tmp_ret), K(ret));
@ -5746,24 +5822,19 @@ int ObPartTransCtx::register_multi_data_source(const ObTxDataSourceType data_sou
TRANS_LOG(WARN, "notify data source for register_succ failed", K(tmp_ret));
} else if (mds_cache_.get_unsubmitted_size() < ObTxMultiDataSourceLog::MAX_PENDING_BUF_SIZE) {
// do nothing
} else if (OB_SUCCESS != (tmp_ret = submit_log_impl_(ObTxLogType::TX_MULTI_DATA_SOURCE_LOG))) {
} else if (OB_SUCCESS
!= (tmp_ret = submit_log_impl_(ObTxLogType::TX_MULTI_DATA_SOURCE_LOG))) {
TRANS_LOG(WARN, "submit mds log failed", K(tmp_ret));
}
}
}
if (OB_FAIL(ret)) {
TRANS_LOG(WARN,
"register MDS redo in part_ctx failed",
K(ret),
K(trans_id_),
K(ls_id_),
K(data_source_type),
K(len),
K(mds_cache_),
K(exec_info_.multi_data_source_));
TRANS_LOG(WARN, "register MDS redo in part_ctx failed", K(ret), K(trans_id_), K(ls_id_),
K(data_source_type), K(len), K(mds_cache_), K(exec_info_.multi_data_source_));
}
REC_TRANS_TRACE_EXT2(tlog_, register_multi_data_source, OB_ID(ret), ret, OB_ID(type), data_source_type);
REC_TRANS_TRACE_EXT2(tlog_, register_multi_data_source, OB_ID(ret), ret, OB_ID(type),
data_source_type);
return ret;
}
@ -6248,7 +6319,8 @@ int ObPartTransCtx::submit_rollback_to_log_(const int64_t from_scn,
ObTxRollbackToLog log(from_scn, to_scn);
ObTxLogCb *log_cb = NULL;
ObTxLogBlockHeader log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_);
ObTxLogBlockHeader
log_block_header(cluster_id_, exec_info_.next_log_entry_no_, trans_id_, exec_info_.scheduler_);
if (OB_FAIL(log_block.init(replay_hint, log_block_header))) {
TRANS_LOG(WARN, "init log block fail", K(ret), KPC(this));
@ -6395,7 +6467,16 @@ int ObPartTransCtx::do_local_tx_end_(TxEndAction tx_end_action)
switch (tx_end_action) {
case TxEndAction::COMMIT_TX: {
ret = do_local_commit_tx_();
if (sub_state_.is_force_abort()) {
if (OB_FAIL(compensate_abort_log_())) {
TRANS_LOG(WARN, "compensate abort log failed", K(ret), K(ls_id_), K(trans_id_),
K(tx_end_action), K(sub_state_));
} else {
ret = OB_TRANS_KILLED;
}
} else {
ret = do_local_commit_tx_();
}
// part_trans_action_ will be set as commit in ObPartTransCtx::commit function
break;
}
@ -6410,6 +6491,10 @@ int ObPartTransCtx::do_local_tx_end_(TxEndAction tx_end_action)
ret = do_force_kill_tx_();
break;
}
case TxEndAction::DELAY_ABORT_TX: {
sub_state_.set_force_abort();
break;
}
default: {
ret = OB_INVALID_ARGUMENT;
TRANS_LOG(WARN, "invalid tx_end_action", K(ret), K(tx_end_action));

View File

@ -253,6 +253,12 @@ private:
int init_memtable_ctx_(const uint64_t tenant_id, const share::ObLSID &ls_id);
bool is_in_2pc_() const;
bool is_logging_() const;
// force abort but not submit abort log
bool need_force_abort_() const;
// force abort but wait abort log_cb
bool is_force_abort_logging_() const;
bool need_record_log_() const;
void reset_redo_lsns_();
void set_prev_record_lsn_(const LogOffSet &prev_record_lsn);

View File

@ -1496,6 +1496,7 @@ int ObTransService::acquire_local_snapshot_(const share::ObLSID &ls_id,
bool leader = false;
SCN snapshot0;
ObLSTxCtxMgr *ls_tx_ctx_mgr = NULL;
const bool can_elr = MTL_IS_PRIMARY_TENANT() ? true : false;
if (OB_FAIL(tx_ctx_mgr_.get_ls_tx_ctx_mgr(ls_id, ls_tx_ctx_mgr))) {
TRANS_LOG(WARN, "get ls_tx_ctx_mgr fail", K(ret), K(ls_id));
} else if (!ls_tx_ctx_mgr->in_leader_serving_state()) {
@ -1507,7 +1508,7 @@ int ObTransService::acquire_local_snapshot_(const share::ObLSID &ls_id,
TRANS_LOG(WARN, "get replica role fail", K(ret), K(ls_id));
} else if (!leader) {
ret = OB_NOT_MASTER;
} else if (FALSE_IT(snapshot0 = tx_version_mgr_.get_max_commit_ts(true))) {
} else if (FALSE_IT(snapshot0 = tx_version_mgr_.get_max_commit_ts(can_elr))) {
} else if (!snapshot0.is_valid_and_not_min()) {
ret = OB_EAGAIN;
} else {

View File

@ -75,13 +75,26 @@ int ObPartTransCtx::do_prepare(bool &no_need_submit_log)
int ret = OB_SUCCESS;
no_need_submit_log = false;
if (exec_info_.is_dup_tx_ || OB_SUCC(search_unsubmitted_dup_table_redo_())) {
no_need_submit_log = true;
if (OB_FAIL(dup_table_tx_redo_sync_())) {
TRANS_LOG(WARN, "dup table tx redo sync failed", K(ret));
if (OB_SUCC(ret)) {
if (sub_state_.is_force_abort()) {
if (OB_FAIL(compensate_abort_log_())) {
TRANS_LOG(WARN, "compensate abort log failed", K(ret), K(ls_id_), K(trans_id_),
K(get_downstream_state()), K(get_upstream_state()), K(sub_state_));
} else {
ret = OB_TRANS_KILLED;
}
}
}
if (OB_SUCC(ret)) {
if (exec_info_.is_dup_tx_ || OB_SUCC(search_unsubmitted_dup_table_redo_())) {
no_need_submit_log = true;
if (OB_FAIL(dup_table_tx_redo_sync_())) {
TRANS_LOG(WARN, "dup table tx redo sync failed", K(ret));
}
} else if (OB_FAIL(generate_prepare_version_())) {
TRANS_LOG(WARN, "generate prepare version failed", K(ret), K(*this));
}
} else if (OB_FAIL(generate_prepare_version_())) {
TRANS_LOG(WARN, "generate prepare version failed", K(ret), K(*this));
}
if (OB_SUCC(ret)) {

View File

@ -686,6 +686,13 @@ int ObPartTransCtx::handle_tx_2pc_prepare_redo_req(const Ob2pcPrepareRedoReqMsg
msg_2pc_cache_ = &msg;
if (OB_FAIL(set_2pc_request_id_(msg.request_id_))) {
TRANS_LOG(WARN, "set request id failed", KR(ret), K(msg), K(*this));
} else if (sub_state_.is_force_abort()) {
if (OB_FAIL(compensate_abort_log_())) {
TRANS_LOG(WARN, "compensate abort log failed", K(ret), K(ls_id_), K(trans_id_),
K(get_downstream_state()), K(get_upstream_state()), K(sub_state_));
} else {
ret = OB_TRANS_KILLED;
}
} else if (OB_FAIL(handle_2pc_req(msg_type))) {
TRANS_LOG(WARN, "handle 2pc request failed", KR(ret), K(msg), K(*this));
}

View File

@ -585,9 +585,7 @@ int ObTransService::get_read_snapshot(ObTxDesc &tx,
snapshot.uncertain_bound_))) {
TRANS_LOG(WARN, "acquire global snapshot fail", K(ret), K(tx));
} else {
if (tx.is_can_elr() && MTL_IS_PRIMARY_TENANT()) {
snapshot.core_.version_ = std::max(snapshot.core_.version_, tx_version_mgr_.get_max_commit_ts(true));
}
// do nothing
}
if (OB_SUCC(ret)) {
snapshot.source_ = ObTxReadSnapshot::SRC::GLOBAL;

View File

@ -150,7 +150,7 @@ int GetTxStateWithSCNFunctor::operator()(const ObTxData &tx_data, ObTxCCCtx *tx_
// return the transaction state_ according to the merge log ts.
// the detailed document is available as follows.
// https://yuque.antfin-inc.com/docs/share/a3160d5e-6e1a-4980-a12e-4af653c6cf57?#
//
if (ObTxData::RUNNING == state || ObTxData::ELR_COMMIT == state) {
// Case 1: data is during execution, so we return the running state with
// INT64_MAX as version

View File

@ -974,7 +974,12 @@ int ObTxAbortLog::init_tx_data_backup(const share::SCN &start_scn)
// ============================== Tx Log Blcok =============================
OB_TX_SERIALIZE_MEMBER(ObTxLogBlockHeader, compat_bytes_, org_cluster_id_, log_entry_no_, tx_id_);
OB_TX_SERIALIZE_MEMBER(ObTxLogBlockHeader,
compat_bytes_,
org_cluster_id_,
log_entry_no_,
tx_id_,
scheduler_);
int ObTxLogBlockHeader::before_serialize()
{
@ -985,7 +990,7 @@ int ObTxLogBlockHeader::before_serialize()
TRANS_LOG(WARN, "reset all compat_bytes_ valid failed", K(ret));
}
} else {
if (OB_FAIL(compat_bytes_.init(3))) {
if (OB_FAIL(compat_bytes_.init(4))) {
TRANS_LOG(WARN, "init compat_bytes_ failed", K(ret));
}
}

View File

@ -901,6 +901,7 @@ public:
org_cluster_id_ = 0;
log_entry_no_ = 0;
tx_id_ = 0;
scheduler_.reset();
}
ObTxLogBlockHeader()
{
@ -909,8 +910,10 @@ public:
};
ObTxLogBlockHeader(const uint64_t org_cluster_id,
const int64_t log_entry_no,
const ObTransID &tx_id)
: org_cluster_id_(org_cluster_id), log_entry_no_(log_entry_no), tx_id_(tx_id)
const ObTransID &tx_id,
const common::ObAddr &scheduler)
: org_cluster_id_(org_cluster_id), log_entry_no_(log_entry_no), tx_id_(tx_id),
scheduler_(scheduler)
{
before_serialize();
}
@ -918,10 +921,11 @@ public:
uint64_t get_org_cluster_id() const { return org_cluster_id_; }
int64_t get_log_entry_no() const { return log_entry_no_; }
const ObTransID &get_tx_id() const { return tx_id_; }
const common::ObAddr &get_scheduler() const { return scheduler_; }
bool is_valid() const { return org_cluster_id_ >= 0; }
TO_STRING_KV(K_(org_cluster_id), K_(log_entry_no), K_(tx_id));
TO_STRING_KV(K_(org_cluster_id), K_(log_entry_no), K_(tx_id), K_(scheduler));
public:
int before_serialize();
@ -931,6 +935,7 @@ private:
uint64_t org_cluster_id_;
int64_t log_entry_no_;
ObTransID tx_id_;
common::ObAddr scheduler_;
};
class ObTxAdaptiveLogBuf

View File

@ -59,7 +59,7 @@ void ObTxLSLogLimit::decide_log_buf_size()
LOG_BUF_SIZE = 0;
ObLogBaseHeader base_header;
ObTxLogHeader tx_header;
ObTxLogBlockHeader block_header(UINT64_MAX, INT64_MAX, INT64_MAX);
ObTxLogBlockHeader block_header(UINT64_MAX, INT64_MAX, INT64_MAX, common::ObAddr());
ObTxStartWorkingLog sw_log(INT_MAX64);
// block_header.before_serialize();

View File

@ -247,11 +247,16 @@ int ObTxReplayExecutor::try_get_tx_ctx_(int64_t tx_id, int64_t tenant_id, const
} else if (OB_TRANS_CTX_NOT_EXIST == ret) {
ret = OB_SUCCESS;
bool tx_ctx_existed = false;
common::ObAddr scheduler;
ObTxCreateArg arg(true, /* for_replay */
tenant_id, tx_id, ls_id, log_block_header_.get_org_cluster_id(),
GET_MIN_CLUSTER_VERSION(), 0, /*session_id*/
scheduler, INT64_MAX, /*trans_expired_time_*/
common::ObAddr scheduler = log_block_header_.get_scheduler();
ObTxCreateArg arg(true, /* for_replay */
tenant_id,
tx_id,
ls_id,
log_block_header_.get_org_cluster_id(),
GET_MIN_CLUSTER_VERSION(),
0, /*session_id*/
scheduler,
INT64_MAX, /*trans_expired_time_*/
ls_tx_srv_->get_trans_service());
if (OB_FAIL(ls_tx_srv_->create_tx_ctx(arg, tx_ctx_existed, ctx_))) {
TRANS_LOG(WARN, "get_tx_ctx error", K(ret), K(tx_id), KP(ctx_));

View File

@ -36,7 +36,7 @@ namespace storage
// design prototype, the goal is a unified abstraction of the merge module.
//
// [1]:
// [2]: https://yuque.antfin.com/docs/share/1e78f01c-73fb-4c32-a002-c2c75ca844a8?#
// [2]:
class ObTxCtxMemtable : public memtable::ObIMemtable, public checkpoint::ObCommonCheckpoint
{
public:

View File

@ -45,7 +45,7 @@ struct TxDataReadSchema
// In Ob4.0, transaction state table is divided into tx data table and tx
// context table. See details :
// https://yuque.antfin.com/docs/share/127d0836-8931-4c9e-8e68-64b900ba91f4?#
//
//
// All operatitons related to tx_data are implemented by ObTxDataTable.
// See details ::

View File

@ -38,15 +38,15 @@ select export_set(9,"Y","N","-",5);
+-----------------------------+
select export_set(9,"左","右","-",5);
+---------------------------------+
| export_set(9,"左","右","-",5) |
| export_set(9,"左","右","-",5) |
+---------------------------------+
| 左-右-右-左-右 |
| 左-右-右-左-右 |
+---------------------------------+
select export_set(9,"上","下","-",5);
+---------------------------------+
| export_set(9,"上","下","-",5) |
| export_set(9,"上","下","-",5) |
+---------------------------------+
| 上-下-下-上-下 |
| 上-下-下-上-下 |
+---------------------------------+
select export_set(5,"Y","N",".",5);
+-----------------------------+

View File

@ -62,25 +62,25 @@ select instr('abcbc', 'bc') from dual;
+----------------------+
select instr('阿里巴巴', '阿里') from dual;
+---------------------------------+
| instr('阿里巴巴', '阿里') |
| instr('阿里巴巴', '阿里') |
+---------------------------------+
| 1 |
+---------------------------------+
select instr('阿里巴巴', '巴巴') from dual;
+---------------------------------+
| instr('阿里巴巴', '巴巴') |
| instr('阿里巴巴', '巴巴') |
+---------------------------------+
| 3 |
+---------------------------------+
select instr('阿里巴巴巴巴', '巴巴') from dual;
+---------------------------------------+
| instr('阿里巴巴巴巴', '巴巴') |
| instr('阿里巴巴巴巴', '巴巴') |
+---------------------------------------+
| 3 |
+---------------------------------------+
select instr('阿里巴巴', '阿里巴巴') from dual;
+---------------------------------------+
| instr('阿里巴巴', '阿里巴巴') |
| instr('阿里巴巴', '阿里巴巴') |
+---------------------------------------+
| 1 |
+---------------------------------------+
@ -116,13 +116,13 @@ select instr('123.400000', null) from dual;
+---------------------------+
select instr(null, '巴巴') from dual;
+-----------------------+
| instr(null, '巴巴') |
| instr(null, '巴巴') |
+-----------------------+
| NULL |
+-----------------------+
select instr('巴巴', null) from dual;
+-----------------------+
| instr('巴巴', null) |
| instr('巴巴', null) |
+-----------------------+
| NULL |
+-----------------------+

View File

@ -1729,7 +1729,7 @@ def str_to_date('1970-02-03 10:56:56', NULL) 12 26 0 Y 128 6 63
+------------------------------------------+
select coalesce(length(lower(null)), length(lower(upper('yssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxddsd'))), length('dir')) from build_in_func_test_table;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def ÿ coalesce(length(lower(null)), length(lower(upper('yssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss 8 20 3 Y 32768 0 63
def coalesce(length(lower(null)), length(lower(upper('yssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss 8 20 3 Y 32768 0 63
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| coalesce(length(lower(null)), length(lower(upper('yssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

View File

@ -2047,10 +2047,10 @@ SELECT * FROM result1//
+------+--------------+--------------+
| id | res1 | res2 |
+------+--------------+--------------+
| 1 | 结果表: | 标签label1 |
| 2 | 结果表: | 标签label2 |
| 3 | 结果表: | 标签label1 |
| 4 | 结果表: | 标签label1 |
| 1 | 结果表: | 标签label1 |
| 2 | 结果表: | 标签label2 |
| 3 | 结果表: | 标签label1 |
| 4 | 结果表: | 标签label1 |
+------+--------------+--------------+
DROP TABLE IF EXISTS result1//
DROP PROCEDURE IF EXISTS `pro_1`//
@ -2213,9 +2213,9 @@ SELECT * FROM t2//
+------+----------------------------------------+---------------------+---------------------+----------------------------+
| id | res1 | d1 | d2 | d3 |
+------+----------------------------------------+---------------------+---------------------+----------------------------+
| 1 | 插入DATETIME类型数据 | 1000-01-01 00:00:00 | 2000-01-01 00:00:00 | 9999-12-31 23:59:59.999999 |
| 2 | 变量形式插入DATETIME类型数据 | 1000-01-01 00:00:00 | 2021-07-03 00:00:00 | 9999-12-31 23:59:59.999999 |
| 3 | 直接插入DATETIME类型数据 | 3000-01-01 00:00:00 | 4000-01-01 00:00:00 | 9999-12-31 23:59:59.999999 |
| 1 | 插入DATETIME类型数据 | 1000-01-01 00:00:00 | 2000-01-01 00:00:00 | 9999-12-31 23:59:59.999999 |
| 2 | 变量形式插入DATETIME类型数据 | 1000-01-01 00:00:00 | 2021-07-03 00:00:00 | 9999-12-31 23:59:59.999999 |
| 3 | 直接插入DATETIME类型数据 | 3000-01-01 00:00:00 | 4000-01-01 00:00:00 | 9999-12-31 23:59:59.999999 |
+------+----------------------------------------+---------------------+---------------------+----------------------------+
### int
@ -2316,7 +2316,7 @@ select fun2()//
+--------------+
| fun2() |
+--------------+
| 隐式提交 |
| 隐式提交 |
+--------------+
select * from t1//

View File

@ -55,7 +55,7 @@ create table t6 (pk int primary key, a int, b int, c int, d int, e int,
##
create table t7(a int, b int, c int, d int, e int, f int, key k1(a,c,b), key k2(a,b,c,d,e));
##
##project/81079/issue/12046883?akProjectId=81079&
create table t8(a int primary key, b int, c int, d int, e int, f int, index k1(b,c,e), index k2(c,d,e,f));
create table tmp (pk int primary key, c1 int, c2 int, c3 int, c4 int, c5 int,
@ -332,7 +332,7 @@ explain select c from t6 where b = 1 and a > 2 union select pk from tmp;
##
explain select * from t7 where a >= 0 and a <= 5 and b = 1;
##
##project/81079/issue/12046883?akProjectId=81079&
explain select * from t8 where e = 1 order by b;
explain select * from t8 where e = 1 or f = 1 order by b;
explain select * from t8 where d = 1 order by b;

View File

@ -129,16 +129,16 @@ select group_concat(c1) from t111_var;
set group_concat_max_len=29;
select group_concat('中文' separator '分隔') from t111_var;
+-------------------------------------------+
| group_concat('中文' separator '分隔') |
| group_concat('中文' separator '分隔') |
+-------------------------------------------+
| 中文分隔中文分隔中 |
| 中文分隔中文分隔中 |
+-------------------------------------------+
set group_concat_max_len=23;
select group_concat('中文' separator '分隔') from t111_var;
+-------------------------------------------+
| group_concat('中文' separator '分隔') |
| group_concat('中文' separator '分隔') |
+-------------------------------------------+
| 中文分隔中文分 |
| 中文分隔中文分 |
+-------------------------------------------+
set group_concat_max_len=1024;

View File

@ -42,7 +42,7 @@ Warning 1292 Truncated incorrect INTEGER value: '0.1'
Warning 1292 Truncated incorrect INTEGER value: '-1.1'
select locate('中', 'a中测试', 1);
+--------------------------------+
| locate('中', 'a中测试', 1) |
| locate('中', 'a中测试', 1) |
+--------------------------------+
| 2 |
+--------------------------------+
@ -85,16 +85,16 @@ select locate('a', 'a', 10000000000000000000000000000000000000000000000000000000
select instr('abc', 'a'), instr('aaaa','a'), instr('a中测试', '中'), instr(null, 'a'), instr('a', null);
+-------------------+-------------------+----------------------------+------------------+------------------+
| instr('abc', 'a') | instr('aaaa','a') | instr('a中测试', '中') | instr(null, 'a') | instr('a', null) |
| instr('abc', 'a') | instr('aaaa','a') | instr('a中测试', '中') | instr(null, 'a') | instr('a', null) |
+-------------------+-------------------+----------------------------+------------------+------------------+
| 1 | 1 | 2 | NULL | NULL |
+-------------------+-------------------+----------------------------+------------------+------------------+
select reverse(''), reverse(null), reverse('你好abc中文'), reverse(12345.123), reverse(null);
+-------------+---------------+----------------------------+--------------------+---------------+
| reverse('') | reverse(null) | reverse('你好abc中文') | reverse(12345.123) | reverse(null) |
| reverse('') | reverse(null) | reverse('你好abc中文') | reverse(12345.123) | reverse(null) |
+-------------+---------------+----------------------------+--------------------+---------------+
| | NULL | 文中cba好你 | 321.54321 | NULL |
| | NULL | 文中cba好你 | 321.54321 | NULL |
+-------------+---------------+----------------------------+--------------------+---------------+
drop table if exists t1;

View File

@ -7562,7 +7562,7 @@ insert into t1 values('10:10:10');
select nullif(z0_test0,'中文字符') from t1;
+---------------------------------+
| nullif(z0_test0,'中文字符') |
| nullif(z0_test0,'中文字符') |
+---------------------------------+
| NULL |
| 123456 |
@ -7685,7 +7685,7 @@ select d1, d2, nullif(d1, null), nullif(null, d1), nullif(d2, null), nullif(null
+---------------------+---------------------+---------------------+------------------+---------------------+------------------+
| d1 | d2 | nullif(d1, null) | nullif(null, d1) | nullif(d2, null) | nullif(null, d2) |
+---------------------+---------------------+---------------------+------------------+---------------------+------------------+
| 中文字符 | 中文字符 | 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 中文字符 | 中文字符 | NULL | 中文字符 | NULL |
| 123456 | 123456 | 123456 | NULL | 123456 | NULL |
| ABCabc | ABCabc | ABCabc | NULL | ABCabc | NULL |
| 2020 | 2020 | 2020 | NULL | 2020 | NULL |
@ -7701,9 +7701,9 @@ select d1, c1, nullif(d1, c1), nullif(c1, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 1 | NULL | 1 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 1 | NULL | NULL |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 1 | NULL | NULL |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 1 | 123456 | 1 |
| 123456 | 123456 | 123456 | 123456 |
@ -7730,9 +7730,9 @@ select d1, c2, nullif(d1, c2), nullif(c2, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2 | NULL | 2 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2 | 中文字符 | 2 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2 | 中文字符 | 2 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2 | NULL | NULL |
| 123456 | 123456 | 123456 | 123456 |
@ -7759,9 +7759,9 @@ select d1, c3, nullif(d1, c3), nullif(c3, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 3 | NULL | 3 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 3 | 中文字符 | 3 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 3 | 中文字符 | 3 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 3 | 123456 | 3 |
| 123456 | 123456 | 123456 | 123456 |
@ -7788,9 +7788,9 @@ select d1, c4, nullif(d1, c4), nullif(c4, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020-10-10 | NULL | 2020-10-10 |
| NULL | 2020-12-12 | NULL | 2020-12-12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 | 中文字符 | 2020-10-10 |
| 中文字符 | 2020-12-12 | 中文字符 | 2020-12-12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 | 中文字符 | 2020-10-10 |
| 中文字符 | 2020-12-12 | 中文字符 | 2020-12-12 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020-10-10 | 123456 | 2020-10-10 |
| 123456 | 2020-12-12 | 123456 | 2020-12-12 |
@ -7817,9 +7817,9 @@ select d1, c5, nullif(d1, c5), nullif(c5, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020-10-10 10:10:10 | NULL | 2020-10-10 10:10:10 |
| NULL | 2020-12-12 10:10:10 | NULL | 2020-12-12 10:10:10 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 |
| 中文字符 | 2020-12-12 10:10:10 | 中文字符 | 2020-12-12 10:10:10 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 |
| 中文字符 | 2020-12-12 10:10:10 | 中文字符 | 2020-12-12 10:10:10 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020-10-10 10:10:10 | 123456 | 2020-10-10 10:10:10 |
| 123456 | 2020-12-12 10:10:10 | 123456 | 2020-12-12 10:10:10 |
@ -7846,9 +7846,9 @@ select d1, c6, nullif(d1, c6), nullif(c6, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 10:10:10 | NULL | 10:10:10 |
| NULL | 12:12:12 | NULL | 12:12:12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 10:10:10 | 中文字符 | 10:10:10 |
| 中文字符 | 12:12:12 | 中文字符 | 12:12:12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 10:10:10 | 中文字符 | 10:10:10 |
| 中文字符 | 12:12:12 | 中文字符 | 12:12:12 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 10:10:10 | 123456 | 10:10:10 |
| 123456 | 12:12:12 | 123456 | 12:12:12 |
@ -7875,9 +7875,9 @@ select d1, c7, nullif(d1, c7), nullif(c7, d1) from t1, t2 order by d1, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020 | NULL | 2020 |
| NULL | 2022 | NULL | 2022 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020 | 中文字符 | 2020 |
| 中文字符 | 2022 | 中文字符 | 2022 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020 | 中文字符 | 2020 |
| 中文字符 | 2022 | 中文字符 | 2022 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020 | 123456 | 2020 |
| 123456 | 2022 | 123456 | 2022 |
@ -7902,28 +7902,28 @@ select d1, c8, nullif(d1, c8), nullif(c8, d1) from t1, t2 order by d1, c1;
| d1 | c8 | nullif(d1, c8) | nullif(c8, d1) |
+---------------------+--------------+---------------------+----------------+
| NULL | NULL | NULL | NULL |
| NULL | 中文字符 | NULL | 中文字符 |
| NULL | 中文字符 | NULL | 中文字符 |
| NULL | ABCabc | NULL | ABCabc |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 中文字符 | NULL | NULL |
| 中文字符 | ABCabc | 中文字符 | ABCabc |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 中文字符 | NULL | NULL |
| 中文字符 | ABCabc | 中文字符 | ABCabc |
| 123456 | NULL | 123456 | NULL |
| 123456 | 中文字符 | 123456 | 中文字符 |
| 123456 | 中文字符 | 123456 | 中文字符 |
| 123456 | ABCabc | 123456 | ABCabc |
| ABCabc | NULL | ABCabc | NULL |
| ABCabc | 中文字符 | ABCabc | 中文字符 |
| ABCabc | 中文字符 | ABCabc | 中文字符 |
| ABCabc | ABCabc | NULL | NULL |
| 2020 | NULL | 2020 | NULL |
| 2020 | 中文字符 | 2020 | 中文字符 |
| 2020 | 中文字符 | 2020 | 中文字符 |
| 2020 | ABCabc | 2020 | ABCabc |
| 2020-10-10 | NULL | 2020-10-10 | NULL |
| 2020-10-10 | 中文字符 | 2020-10-10 | 中文字符 |
| 2020-10-10 | 中文字符 | 2020-10-10 | 中文字符 |
| 2020-10-10 | ABCabc | 2020-10-10 | ABCabc |
| 2020-10-10 10:10:10 | NULL | 2020-10-10 10:10:10 | NULL |
| 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 | 中文字符 |
| 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 | 中文字符 |
| 2020-10-10 10:10:10 | ABCabc | 2020-10-10 10:10:10 | ABCabc |
| 10:10:10 | NULL | 10:10:10 | NULL |
| 10:10:10 | 中文字符 | 10:10:10 | 中文字符 |
| 10:10:10 | 中文字符 | 10:10:10 | 中文字符 |
| 10:10:10 | ABCabc | 10:10:10 | ABCabc |
+---------------------+--------------+---------------------+----------------+
@ -7934,9 +7934,9 @@ select d2, c1, nullif(d2, c1), nullif(c1, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 1 | NULL | 1 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 1 | NULL | NULL |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 1 | NULL | NULL |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 1 | 123456 | 1 |
| 123456 | 123456 | 123456 | 123456 |
@ -7963,9 +7963,9 @@ select d2, c2, nullif(d2, c2), nullif(c2, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2 | NULL | 2 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2 | 中文字符 | 2 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2 | 中文字符 | 2 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2 | NULL | NULL |
| 123456 | 123456 | 123456 | 123456 |
@ -7992,9 +7992,9 @@ select d2, c3, nullif(d2, c3), nullif(c3, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 3 | NULL | 3 |
| NULL | 123456 | NULL | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 3 | 中文字符 | 3 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 3 | 中文字符 | 3 |
| 中文字符 | 123456 | 中文字符 | 123456 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 3 | 123456 | 3 |
| 123456 | 123456 | 123456 | 123456 |
@ -8021,9 +8021,9 @@ select d2, c4, nullif(d2, c4), nullif(c4, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020-10-10 | NULL | 2020-10-10 |
| NULL | 2020-12-12 | NULL | 2020-12-12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 | 中文字符 | 2020-10-10 |
| 中文字符 | 2020-12-12 | 中文字符 | 2020-12-12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 | 中文字符 | 2020-10-10 |
| 中文字符 | 2020-12-12 | 中文字符 | 2020-12-12 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020-10-10 | 123456 | 2020-10-10 |
| 123456 | 2020-12-12 | 123456 | 2020-12-12 |
@ -8050,9 +8050,9 @@ select d2, c5, nullif(d2, c5), nullif(c5, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020-10-10 10:10:10 | NULL | 2020-10-10 10:10:10 |
| NULL | 2020-12-12 10:10:10 | NULL | 2020-12-12 10:10:10 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 |
| 中文字符 | 2020-12-12 10:10:10 | 中文字符 | 2020-12-12 10:10:10 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 |
| 中文字符 | 2020-12-12 10:10:10 | 中文字符 | 2020-12-12 10:10:10 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020-10-10 10:10:10 | 123456 | 2020-10-10 10:10:10 |
| 123456 | 2020-12-12 10:10:10 | 123456 | 2020-12-12 10:10:10 |
@ -8079,9 +8079,9 @@ select d2, c6, nullif(d2, c6), nullif(c6, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 10:10:10 | NULL | 10:10:10 |
| NULL | 12:12:12 | NULL | 12:12:12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 10:10:10 | 中文字符 | 10:10:10 |
| 中文字符 | 12:12:12 | 中文字符 | 12:12:12 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 10:10:10 | 中文字符 | 10:10:10 |
| 中文字符 | 12:12:12 | 中文字符 | 12:12:12 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 10:10:10 | 123456 | 10:10:10 |
| 123456 | 12:12:12 | 123456 | 12:12:12 |
@ -8108,9 +8108,9 @@ select d2, c7, nullif(d2, c7), nullif(c7, d2) from t1, t2 order by d2, c1;
| NULL | NULL | NULL | NULL |
| NULL | 2020 | NULL | 2020 |
| NULL | 2022 | NULL | 2022 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020 | 中文字符 | 2020 |
| 中文字符 | 2022 | 中文字符 | 2022 |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 2020 | 中文字符 | 2020 |
| 中文字符 | 2022 | 中文字符 | 2022 |
| 123456 | NULL | 123456 | NULL |
| 123456 | 2020 | 123456 | 2020 |
| 123456 | 2022 | 123456 | 2022 |
@ -8135,27 +8135,27 @@ select d2, c8, nullif(d2, c8), nullif(c8, d2) from t1, t2 order by d2, c1;
| d2 | c8 | nullif(d2, c8) | nullif(c8, d2) |
+---------------------+--------------+---------------------+----------------+
| NULL | NULL | NULL | NULL |
| NULL | 中文字符 | NULL | 中文字符 |
| NULL | 中文字符 | NULL | 中文字符 |
| NULL | ABCabc | NULL | ABCabc |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 中文字符 | NULL | NULL |
| 中文字符 | ABCabc | 中文字符 | ABCabc |
| 中文字符 | NULL | 中文字符 | NULL |
| 中文字符 | 中文字符 | NULL | NULL |
| 中文字符 | ABCabc | 中文字符 | ABCabc |
| 123456 | NULL | 123456 | NULL |
| 123456 | 中文字符 | 123456 | 中文字符 |
| 123456 | 中文字符 | 123456 | 中文字符 |
| 123456 | ABCabc | 123456 | ABCabc |
| ABCabc | NULL | ABCabc | NULL |
| ABCabc | 中文字符 | ABCabc | 中文字符 |
| ABCabc | 中文字符 | ABCabc | 中文字符 |
| ABCabc | ABCabc | NULL | NULL |
| 2020 | NULL | 2020 | NULL |
| 2020 | 中文字符 | 2020 | 中文字符 |
| 2020 | 中文字符 | 2020 | 中文字符 |
| 2020 | ABCabc | 2020 | ABCabc |
| 2020-10-10 | NULL | 2020-10-10 | NULL |
| 2020-10-10 | 中文字符 | 2020-10-10 | 中文字符 |
| 2020-10-10 | 中文字符 | 2020-10-10 | 中文字符 |
| 2020-10-10 | ABCabc | 2020-10-10 | ABCabc |
| 2020-10-10 10:10:10 | NULL | 2020-10-10 10:10:10 | NULL |
| 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 | 中文字符 |
| 2020-10-10 10:10:10 | 中文字符 | 2020-10-10 10:10:10 | 中文字符 |
| 2020-10-10 10:10:10 | ABCabc | 2020-10-10 10:10:10 | ABCabc |
| 10:10:10 | NULL | 10:10:10 | NULL |
| 10:10:10 | 中文字符 | 10:10:10 | 中文字符 |
| 10:10:10 | 中文字符 | 10:10:10 | 中文字符 |
| 10:10:10 | ABCabc | 10:10:10 | ABCabc |
+---------------------+--------------+---------------------+----------------+

View File

@ -6173,113 +6173,113 @@ set character_set_server=utf8;
set character_set_connection=binary;
select hex(lpad('钡', 2, 'c'));
+--------------------------+
| hex(lpad('钡', 2, 'c')) |
| hex(lpad('钡', 2, 'c')) |
+--------------------------+
| E992 |
+--------------------------+
set character_set_connection=utf8;
select hex(lpad('钡', 2, 'c'));
+--------------------------+
| hex(lpad('钡', 2, 'c')) |
| hex(lpad('钡', 2, 'c')) |
+--------------------------+
| 63E992A1 |
+--------------------------+
select lpad('a', 1, '阿斯'), length(lpad('a', 1, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 1, '阿斯') | length(lpad('a', 1, '阿斯')) |
| lpad('a', 1, '阿斯') | length(lpad('a', 1, '阿斯')) |
+------------------------+--------------------------------+
| a | 1 |
+------------------------+--------------------------------+
select lpad('a', 2, '阿斯'), length(lpad('a', 2, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 2, '阿斯') | length(lpad('a', 2, '阿斯')) |
| lpad('a', 2, '阿斯') | length(lpad('a', 2, '阿斯')) |
+------------------------+--------------------------------+
| 阿a | 4 |
| 阿a | 4 |
+------------------------+--------------------------------+
select lpad('a', 3, '阿斯'), length(lpad('a', 3, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 3, '阿斯') | length(lpad('a', 3, '阿斯')) |
| lpad('a', 3, '阿斯') | length(lpad('a', 3, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯a | 7 |
| 阿斯a | 7 |
+------------------------+--------------------------------+
select lpad('a', 4, '阿斯'), length(lpad('a', 4, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 4, '阿斯') | length(lpad('a', 4, '阿斯')) |
| lpad('a', 4, '阿斯') | length(lpad('a', 4, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯阿a | 10 |
| 阿斯阿a | 10 |
+------------------------+--------------------------------+
select lpad('a', 5, '阿斯'), length(lpad('a', 5, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 5, '阿斯') | length(lpad('a', 5, '阿斯')) |
| lpad('a', 5, '阿斯') | length(lpad('a', 5, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯阿斯a | 13 |
| 阿斯阿斯a | 13 |
+------------------------+--------------------------------+
select lpad('a', 6, '阿斯'), length(lpad('a', 6, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 6, '阿斯') | length(lpad('a', 6, '阿斯')) |
| lpad('a', 6, '阿斯') | length(lpad('a', 6, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯阿斯阿a | 16 |
| 阿斯阿斯阿a | 16 |
+------------------------+--------------------------------+
select lpad('a', 7, '阿斯'), length(lpad('a', 7, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 7, '阿斯') | length(lpad('a', 7, '阿斯')) |
| lpad('a', 7, '阿斯') | length(lpad('a', 7, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯阿斯阿斯a | 19 |
| 阿斯阿斯阿斯a | 19 |
+------------------------+--------------------------------+
select lpad('a', 8, '阿斯'), length(lpad('a', 8, '阿斯')) from dual;
+------------------------+--------------------------------+
| lpad('a', 8, '阿斯') | length(lpad('a', 8, '阿斯')) |
| lpad('a', 8, '阿斯') | length(lpad('a', 8, '阿斯')) |
+------------------------+--------------------------------+
| 阿斯阿斯阿斯阿a | 22 |
| 阿斯阿斯阿斯阿a | 22 |
+------------------------+--------------------------------+
select rpad('a', 1, '阿斯'), length(rpad('a', 1, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 1, '阿斯') | length(rpad('a', 1, '阿斯')) |
| rpad('a', 1, '阿斯') | length(rpad('a', 1, '阿斯')) |
+------------------------+--------------------------------+
| a | 1 |
+------------------------+--------------------------------+
select rpad('a', 2, '阿斯'), length(rpad('a', 2, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 2, '阿斯') | length(rpad('a', 2, '阿斯')) |
| rpad('a', 2, '阿斯') | length(rpad('a', 2, '阿斯')) |
+------------------------+--------------------------------+
| a阿 | 4 |
| a阿 | 4 |
+------------------------+--------------------------------+
select rpad('a', 3, '阿斯'), length(rpad('a', 3, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 3, '阿斯') | length(rpad('a', 3, '阿斯')) |
| rpad('a', 3, '阿斯') | length(rpad('a', 3, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯 | 7 |
| a阿斯 | 7 |
+------------------------+--------------------------------+
select rpad('a', 4, '阿斯'), length(rpad('a', 4, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 4, '阿斯') | length(rpad('a', 4, '阿斯')) |
| rpad('a', 4, '阿斯') | length(rpad('a', 4, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯阿 | 10 |
| a阿斯阿 | 10 |
+------------------------+--------------------------------+
select rpad('a', 5, '阿斯'), length(rpad('a', 5, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 5, '阿斯') | length(rpad('a', 5, '阿斯')) |
| rpad('a', 5, '阿斯') | length(rpad('a', 5, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯阿斯 | 13 |
| a阿斯阿斯 | 13 |
+------------------------+--------------------------------+
select rpad('a', 6, '阿斯'), length(rpad('a', 6, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 6, '阿斯') | length(rpad('a', 6, '阿斯')) |
| rpad('a', 6, '阿斯') | length(rpad('a', 6, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯阿斯阿 | 16 |
| a阿斯阿斯阿 | 16 |
+------------------------+--------------------------------+
select rpad('a', 7, '阿斯'), length(rpad('a', 7, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 7, '阿斯') | length(rpad('a', 7, '阿斯')) |
| rpad('a', 7, '阿斯') | length(rpad('a', 7, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯阿斯阿斯 | 19 |
| a阿斯阿斯阿斯 | 19 |
+------------------------+--------------------------------+
select rpad('a', 8, '阿斯'), length(rpad('a', 8, '阿斯')) from dual;
+------------------------+--------------------------------+
| rpad('a', 8, '阿斯') | length(rpad('a', 8, '阿斯')) |
| rpad('a', 8, '阿斯') | length(rpad('a', 8, '阿斯')) |
+------------------------+--------------------------------+
| a阿斯阿斯阿斯阿 | 22 |
| a阿斯阿斯阿斯阿 | 22 |
+------------------------+--------------------------------+

View File

@ -44,7 +44,7 @@ select regexp_like(123, 123) from dual;
+-----------------------+
select regexp_like('我是好人', '.是.*') from dual;
+---------------------------------------+
| regexp_like('我是好人', '.是.*') |
| regexp_like('我是好人', '.是.*') |
+---------------------------------------+
| 1 |
+---------------------------------------+
@ -118,7 +118,7 @@ select regexp_instr(12341834, 1.3, '1', '2', 1) from dual;
+------------------------------------------+
select regexp_instr('我是好人', '是.') from dual;
+--------------------------------------+
| regexp_instr('我是好人', '是.') |
| regexp_instr('我是好人', '是.') |
+--------------------------------------+
| 2 |
+--------------------------------------+
@ -174,9 +174,9 @@ Warnings:
Warning 1292 Truncated incorrect INTEGER value: '1.9'
select regexp_replace('我是好人', '是.') from dual;
+----------------------------------------+
| regexp_replace('我是好人', '是.') |
| regexp_replace('我是好人', '是.') |
+----------------------------------------+
| 我人 |
| 我人 |
+----------------------------------------+
select regexp_replace('abcadef', 'a.') from dual;
@ -270,8 +270,8 @@ select regexp_replace(12341834, 1.3, 99, '1', '2') from dual;
+---------------------------------------------+
select regexp_replace('我是好人', '是.', '.....') from dual;
+-------------------------------------------------+
| regexp_replace('我是好人', '是.', '.....') |
| regexp_replace('我是好人', '是.', '.....') |
+-------------------------------------------------+
| 我.....人 |
| 我.....人 |
+-------------------------------------------------+

View File

@ -170,13 +170,13 @@ drop table t1;
select SUBSTRING( TRIM( BOTH CONVERT( 'a', BINARY( 0 ) ) FROM '+-Ã÷﹢﹣±/= â¥â' ) , 1 ,20) ;
+-------------------------------------------------------------------------------------------------------+
| SUBSTRING( TRIM( BOTH CONVERT( 'a', BINARY( 0 ) ) FROM '+-Ã÷﹢﹣±/= â¥â' ) , 1 ,20) |
| SUBSTRING( TRIM( BOTH CONVERT( 'a', BINARY( 0 ) ) FROM '+-Ã÷﹢﹣±/= â¥â' ) , 1 ,20) |
+-------------------------------------------------------------------------------------------------------+
| +-Ã÷﹢﹣±/= â¥â |
| +-Ã÷﹢﹣±/= â¥â |
+-------------------------------------------------------------------------------------------------------+
select collation(TRIM( BOTH _binary'a' FROM '+-Ã÷﹢﹣±/= â¥â' )) ;
+-----------------------------------------------------------------------------+
| collation(TRIM( BOTH _binary'a' FROM '+-Ã÷﹢﹣±/= â¥â' )) |
| collation(TRIM( BOTH _binary'a' FROM '+-Ã÷﹢﹣±/= â¥â' )) |
+-----------------------------------------------------------------------------+
| utf8mb4_general_ci |
+-----------------------------------------------------------------------------+

View File

@ -199,7 +199,7 @@ private:
int ObTxLogBlockBuilder::next_log_block()
{
int ret = OB_SUCCESS;
ObTxLogBlockHeader block_header(cluster_id_, log_entry_no_, tx_id_);
ObTxLogBlockHeader block_header(cluster_id_, log_entry_no_, tx_id_, common::ObAddr());
tx_log_block_.reset();
if (OB_FAIL(tx_log_block_.init(tx_id_, block_header))) {

View File

@ -9,6 +9,7 @@ endfunction()
tx_it_test(test_tx)
tx_it_test(test_tx_free_route)
tx_it_test(test_tx_ctx)
#tx_it_test(test_tx_perf)

View File

@ -0,0 +1,157 @@
#include <gtest/gtest.h>
#include <thread>
#define private public
#define protected public
#include "storage/tx/ob_trans_define.h"
#include "storage/tx/ob_trans_part_ctx.h"
#include "storage/tx/ob_trans_service.h"
#define USING_LOG_PREFIX TRANS
#include "../mock_utils/async_util.h"
#include "test_tx_dsl.h"
#include "tx_node.h"
namespace oceanbase
{
using namespace ::testing;
using namespace transaction;
using namespace share;
namespace concurrent_control
{
int check_sequence_set_violation(const concurrent_control::ObWriteFlag,
const int64_t,
const ObTransID,
const blocksstable::ObDmlFlag,
const int64_t,
const ObTransID,
const blocksstable::ObDmlFlag,
const int64_t)
{
return OB_SUCCESS;
}
} // namespace concurrent_control
class ObTestTxCtx : public ::testing::Test
{
public:
virtual void SetUp() override
{
ObMallocAllocator::get_instance()->create_and_add_tenant_allocator(1001);
const uint64_t tv = ObTimeUtility::current_time();
ObCurTraceId::set(&tv);
GCONF._ob_trans_rpc_timeout = 500;
ObClockGenerator::init();
const testing::TestInfo *const test_info =
testing::UnitTest::GetInstance()->current_test_info();
auto test_name = test_info->name();
_TRANS_LOG(INFO, ">>>> starting test : %s", test_name);
}
virtual void TearDown() override
{
const testing::TestInfo *const test_info =
testing::UnitTest::GetInstance()->current_test_info();
auto test_name = test_info->name();
_TRANS_LOG(INFO, ">>>> tearDown test : %s", test_name);
ObClockGenerator::destroy();
ObMallocAllocator::get_instance()->recycle_tenant_allocator(1001);
}
MsgBus bus_;
};
TEST_F(ObTestTxCtx, DelayAbort)
{
ObTxPartList backup_parts;
START_ONE_TX_NODE(n1);
PREPARE_TX_PARAM(tx_param);
PREPARE_TX(n1, tx);
{ // prepare snapshot for write
ObTxReadSnapshot snapshot;
ASSERT_EQ(OB_SUCCESS,
n1->get_read_snapshot(tx, tx_param.isolation_, n1->ts_after_ms(100), snapshot));
CREATE_IMPLICIT_SAVEPOINT(n1, tx, tx_param, sp1);
ASSERT_EQ(OB_SUCCESS, n1->create_implicit_savepoint(tx, tx_param, sp1));
ASSERT_EQ(OB_SUCCESS, n1->write(tx, snapshot, 100, 112));
}
ASSERT_EQ(OB_SUCCESS, backup_parts.assign(tx.parts_));
tx.parts_.reset();
ObLSTxCtxMgr *ls_tx_ctx_mgr = nullptr;
ObPartTransCtx *tx_ctx = nullptr;
ASSERT_EQ(OB_SUCCESS, n1->txs_.tx_ctx_mgr_.get_ls_tx_ctx_mgr(n1->ls_id_, ls_tx_ctx_mgr));
{
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->get_tx_ctx(tx.tx_id_, false /*for_replay*/, tx_ctx));
GCONF._private_buffer_size = 1;
// ASSERT_EQ(OB_SUCCESS, tx_ctx->submit_log_impl_(ObTxLogType::TX_REDO_LOG));
ASSERT_EQ(OB_SUCCESS, tx_ctx->submit_redo_log(false /*is_freeze*/));
TRANS_LOG(INFO, "[TEST] after submit redo", K(tx_ctx->trans_id_),
K(tx_ctx->exec_info_.max_applied_log_ts_));
n1->wait_all_redolog_applied();
TRANS_LOG(INFO, "[TEST] after on_success redo", K(tx_ctx->trans_id_),
K(tx_ctx->exec_info_.max_applied_log_ts_));
ASSERT_EQ(true, tx_ctx->exec_info_.redo_lsns_.count() > 0);
ASSERT_EQ(true, tx_ctx->exec_info_.max_applied_log_ts_.is_valid());
ASSERT_EQ(ObTxState::INIT, tx_ctx->exec_info_.state_);
ASSERT_EQ(false, tx_ctx->is_follower_());
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->revert_tx_ctx(tx_ctx));
}
ls_tx_ctx_mgr->switch_to_follower_forcedly();
{
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->get_tx_ctx(tx.tx_id_, true /*for_replay*/, tx_ctx));
ASSERT_EQ(true, tx_ctx->exec_info_.redo_lsns_.count() > 0);
ASSERT_EQ(true, tx_ctx->exec_info_.max_applied_log_ts_.is_valid());
ASSERT_EQ(ObTxState::INIT, tx_ctx->exec_info_.state_);
ASSERT_EQ(true, tx_ctx->is_follower_());
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->revert_tx_ctx(tx_ctx));
}
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->switch_to_leader());
n1->wait_all_redolog_applied();
{
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->get_tx_ctx(tx.tx_id_, false /*for_replay*/, tx_ctx));
TRANS_LOG(INFO, "[TEST] after leader takeover", K(tx_ctx->trans_id_),
K(tx_ctx->exec_info_.state_), K(tx_ctx->exec_info_.max_applied_log_ts_));
ASSERT_EQ(true, tx_ctx->exec_info_.redo_lsns_.count() > 0);
ASSERT_EQ(true, tx_ctx->exec_info_.max_applied_log_ts_.is_valid());
ASSERT_EQ(true, tx_ctx->sub_state_.is_force_abort());
ASSERT_EQ(false, tx_ctx->sub_state_.is_state_log_submitted());
ASSERT_EQ(ObTxState::INIT, tx_ctx->exec_info_.state_);
ASSERT_EQ(false, tx_ctx->is_follower_());
ASSERT_EQ(OB_SUCCESS, ls_tx_ctx_mgr->revert_tx_ctx(tx_ctx));
}
{ // prepare snapshot for write
ObTxReadSnapshot snapshot;
ASSERT_EQ(OB_SUCCESS,
n1->get_read_snapshot(tx, tx_param.isolation_, n1->ts_after_ms(100), snapshot));
CREATE_IMPLICIT_SAVEPOINT(n1, tx, tx_param, sp2);
ASSERT_EQ(OB_SUCCESS, n1->create_implicit_savepoint(tx, tx_param, sp2));
ASSERT_EQ(OB_TRANS_KILLED, n1->write(tx, snapshot, 1110, 1120));
}
ASSERT_EQ(OB_SUCCESS, tx.parts_.assign(backup_parts));
ASSERT_EQ(OB_TRANS_KILLED, n1->commit_tx(tx, n1->ts_after_ms(500)));
ASSERT_EQ(OB_SUCCESS, n1->release_tx(tx));
ASSERT_EQ(OB_SUCCESS, n1->wait_all_tx_ctx_is_destoryed());
ASSERT_EQ(OB_SUCCESS, n1->txs_.tx_ctx_mgr_.revert_ls_tx_ctx_mgr(ls_tx_ctx_mgr));
}
} // namespace oceanbase
int main(int argc, char **argv)
{
int64_t tx_id = 21533427;
uint64_t h = murmurhash(&tx_id, sizeof(tx_id), 0);
system("rm -rf test_tx_ctx*.log*");
ObLogger &logger = ObLogger::get_logger();
logger.set_file_name("test_tx_ctx.log", true, false,
"test_tx_ctx_rs.log", // rs
"test_tx_ctx_election.log", // election
"test_tx_ctx_audit.log"); // audit
logger.set_log_level(OB_LOG_LEVEL_DEBUG);
::testing::InitGoogleTest(&argc, argv);
TRANS_LOG(INFO, "mmhash:", K(h));
return RUN_ALL_TESTS();
}

View File

@ -112,7 +112,7 @@ TEST_F(TestObTxLog, tx_log_block_header)
int64_t pos = 0;
ObTxLogBlock fill_block, replay_block;
ObTxLogBlockHeader fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID));
ObTxLogBlockHeader fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID), TEST_ADDR);
ASSERT_EQ(OB_SUCCESS, fill_block.init(TEST_TX_ID, fill_block_header));
// check log_block_header
@ -205,7 +205,7 @@ TEST_F(TestObTxLog, tx_log_body_except_redo)
ObTxAbortLog fill_abort(TEST_TX_BUFFER_NODE_ARRAY);
ObTxRecordLog fill_record(TEST_LOG_OFFSET, TEST_LOG_OFFSET_ARRY);
ObTxLogBlockHeader header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID));
ObTxLogBlockHeader header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID), TEST_ADDR);
ASSERT_EQ(OB_SUCCESS, fill_block.init(TEST_TX_ID, header));
ASSERT_EQ(OB_SUCCESS, fill_block.add_new_log(fill_active_state));
ASSERT_EQ(OB_SUCCESS, fill_block.add_new_log(fill_commit_state));
@ -320,7 +320,7 @@ TEST_F(TestObTxLog, tx_log_body_redo)
TEST_LOG_OFFSET,
TEST_INFO_ARRAY);
ObTxLogBlockHeader fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID));
ObTxLogBlockHeader fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID), TEST_ADDR);
ASSERT_EQ(OB_SUCCESS, fill_block.init(TEST_TX_ID, fill_block_header));
ObString TEST_MUTATOR_BUF("FFF");
@ -506,6 +506,8 @@ TEST_F(TestObTxLog, test_default_log_deserialize)
replay_member_cnt++;
EXPECT_EQ(fill_block_header.get_tx_id().get_id(), replay_block_header.get_tx_id().get_id());
replay_member_cnt++;
EXPECT_EQ(fill_block_header.get_scheduler(), replay_block_header.get_scheduler());
replay_member_cnt++;
EXPECT_EQ(replay_member_cnt, fill_member_cnt);
ObTxActiveInfoLogTempRef active_temp_ref;
@ -686,8 +688,8 @@ void test_big_commit_info_log(int64_t log_size)
TEST_IS_DUP, TEST_CAN_ELR, TEST_TRACE_ID_STR, TEST_TRCE_INFO,
TEST_LOG_OFFSET, TEST_BIG_REDO_LSN_ARRAY, TEST_LS_ARRAY,
TEST_CLUSTER_VERSION, TEST_XID);
ObTxLogBlockHeader fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO,
ObTransID(TEST_TX_ID));
ObTxLogBlockHeader
fill_block_header(TEST_ORG_CLUSTER_ID, TEST_LOG_ENTRY_NO, ObTransID(TEST_TX_ID), TEST_ADDR);
ASSERT_EQ(OB_SUCCESS, fill_block.init(TEST_TX_ID, fill_block_header));
ASSERT_EQ(OB_LOG_TOO_LARGE, fill_block.add_new_log(fill_commit_state, &fill_big_segment));