From 43c435fe207eb1e0092922ba798b80475dcb6830 Mon Sep 17 00:00:00 2001 From: cqliang1995 Date: Fri, 15 Mar 2024 17:15:43 +0000 Subject: [PATCH] fix dblink transaction bug --- .../lib/mysqlclient/ob_dblink_error_trans.cpp | 236 ++++++++++++++ .../lib/mysqlclient/ob_dblink_error_trans.h | 40 +++ .../src/lib/mysqlclient/ob_isql_connection.h | 17 +- .../lib/mysqlclient/ob_isql_connection_pool.h | 7 +- .../src/lib/mysqlclient/ob_mysql_proxy.cpp | 25 +- .../lib/mysqlclient/ob_mysql_statement.cpp | 2 +- .../src/lib/mysqlclient/ob_tenant_oci_envs.h | 9 +- src/observer/omt/ob_multi_tenant.cpp | 4 + src/share/rc/ob_tenant_base.h | 4 +- .../schema/ob_schema_service_sql_impl.cpp | 24 +- .../code_generator/ob_static_engine_cg.cpp | 81 ++++- src/sql/dblink/ob_dblink_utils.cpp | 299 ++++++++++++++---- src/sql/dblink/ob_dblink_utils.h | 40 ++- src/sql/engine/dml/ob_link_dml_op.cpp | 26 +- src/sql/engine/dml/ob_link_op.cpp | 141 +++------ src/sql/engine/dml/ob_link_op.h | 16 +- src/sql/engine/ob_physical_plan.cpp | 6 - src/sql/engine/ob_physical_plan.h | 4 +- src/sql/engine/ob_physical_plan_ctx.cpp | 6 +- src/sql/engine/ob_physical_plan_ctx.h | 15 + src/sql/engine/sequence/ob_sequence_op.cpp | 16 +- src/sql/engine/table/ob_link_scan_op.cpp | 99 +++--- src/sql/engine/table/ob_link_scan_op.h | 1 - src/sql/ob_result_set.cpp | 62 +++- src/sql/ob_result_set.h | 2 + src/sql/ob_spi.cpp | 7 + src/sql/ob_sql_trans_control.cpp | 84 ++++- src/sql/ob_sql_trans_control.h | 1 + src/sql/ob_sql_utils.cpp | 30 +- src/sql/ob_sql_utils.h | 13 +- src/sql/optimizer/ob_del_upd_log_plan.cpp | 7 +- src/sql/optimizer/ob_log_link.cpp | 19 +- src/sql/optimizer/ob_log_link_dml.h | 2 + src/sql/optimizer/ob_select_log_plan.cpp | 41 +-- src/sql/printer/ob_delete_stmt_printer.h | 5 +- src/sql/printer/ob_dml_stmt_printer.cpp | 110 ++++++- src/sql/printer/ob_dml_stmt_printer.h | 5 +- src/sql/printer/ob_insert_all_stmt_printer.h | 5 +- src/sql/printer/ob_insert_stmt_printer.h | 5 +- src/sql/printer/ob_merge_stmt_printer.h | 5 +- src/sql/printer/ob_select_stmt_printer.cpp | 3 +- src/sql/printer/ob_select_stmt_printer.h | 5 +- src/sql/printer/ob_update_stmt_printer.h | 5 +- src/sql/resolver/dml/ob_dml_resolver.cpp | 55 +++- src/sql/resolver/dml/ob_dml_resolver.h | 2 + src/sql/resolver/dml/ob_hint.cpp | 64 +++- src/sql/resolver/dml/ob_hint.h | 38 ++- .../dml/ob_sequence_namespace_checker.cpp | 38 +-- src/sql/resolver/dml/ob_sql_hint.cpp | 4 +- src/sql/rewrite/ob_transform_dblink.cpp | 5 +- 50 files changed, 1287 insertions(+), 453 deletions(-) diff --git a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp index e8f7ad3584..a8a272bca7 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp @@ -44,10 +44,17 @@ bool __attribute__((weak)) get_enable_dblink_cfg() return true; } +uint64_t __attribute__((weak)) get_current_tenant_id_for_dblink() +{ + return oceanbase::OB_INVALID_ID; +} + namespace oceanbase { namespace common { +namespace sqlclient +{ int sqlclient::ObDblinkErrorTrans::external_errno_to_ob_errno(bool is_oracle_err, int external_errno, @@ -88,5 +95,234 @@ int sqlclient::ObDblinkErrorTrans::external_errno_to_ob_errno(bool is_oracle_err return ret; } +#ifdef OB_BUILD_DBLINK +int ObTenantDblinkKeeper::clean_dblink_conn(uint32_t sessid, bool force_disconnect) +{ + int ret = OB_SUCCESS; + int64_t value = 0; + obsys::ObRLockGuard wg(lock_); + if (!dblink_conn_map_.created()) { + ret = OB_NOT_INIT; + LOG_WARN("dblink_conn_map_ is not inited", K(ret), K(tenant_id_), K(sessid)); + } else if (OB_FAIL(dblink_conn_map_.get_refactored(sessid, value))) { + if (OB_HASH_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get connection from map", K(ret), K(sessid)); + } + } else if (0 == value) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("value is 0", K(ret), K(value), K(sessid)); + } else { + common::sqlclient::ObISQLConnection *connection = reinterpret_cast(value); + while (OB_NOT_NULL(connection) && OB_SUCC(ret)) { + common::sqlclient::ObISQLConnection *next = connection->get_next_conn(); + connection->dblink_wlock(); //prevent connection still in use + connection->set_reverse_link_creadentials(false); + common::sqlclient::ObCommonServerConnectionPool * server_conn_pool = connection->get_common_server_pool(); + const bool need_disconnect = force_disconnect || !connection->usable(); + if (NULL == server_conn_pool) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("server_conn_pool of dblink connection is NULL", K(tenant_id_), K(sessid), K(connection), K(ret)); + } else if (OB_FAIL(server_conn_pool->release(connection, !need_disconnect))) { + LOG_WARN("session failed to release dblink connection", K(tenant_id_), K(sessid), K(connection), K(ret)); + } else { + LOG_TRACE("session succ to release dblink connection", K(tenant_id_), K(sessid), K(connection), K(ret)); + } + connection->dblink_unwlock(); + connection = next; + } + if (OB_SUCC(ret) && OB_FAIL(dblink_conn_map_.erase_refactored(sessid))) { + LOG_WARN("failed to erase_refactored", K(tenant_id_), K(sessid), K(ret));; + } + } + return ret; +} + +int ObTenantDblinkKeeper::set_dblink_conn(uint32_t sessid, common::sqlclient::ObISQLConnection *dblink_conn) +{ + int ret = OB_SUCCESS; + obsys::ObRLockGuard wg(lock_); + if (!dblink_conn_map_.created()) { + ret = OB_NOT_INIT; + LOG_WARN("dblink_conn_map_ is not inited", K(ret), K(tenant_id_), K(sessid)); + } else if (OB_ISNULL(dblink_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), K(tenant_id_), K(sessid)); + } else { + int64_t value = 0; + if (OB_FAIL(dblink_conn_map_.get_refactored(sessid, value))) { + if (OB_HASH_NOT_EXIST == ret) { + ret = OB_SUCCESS; + if (OB_FAIL(dblink_conn_map_.set_refactored(sessid, reinterpret_cast(dblink_conn)))) { + LOG_WARN("failed to set refactored", K(ret), K(tenant_id_), K(sessid)); + } else { + dblink_conn->set_next_conn(NULL); + } + } else { + LOG_WARN("failed to get connection from map", K(ret), K(sessid)); + } + } else if (0 == value) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("value is 0", K(ret), K(value), K(sessid)); + } else { + common::sqlclient::ObISQLConnection *connection = reinterpret_cast(value); + while (OB_NOT_NULL(connection)) { + if (dblink_conn == connection) { + break; + } + connection = connection->get_next_conn(); + } + if (OB_NOT_NULL(connection)) { + //do nothing + } else { + common::sqlclient::ObISQLConnection *header = reinterpret_cast(value); + common::sqlclient::ObISQLConnection *temp = header->get_next_conn(); + header->set_next_conn(dblink_conn); + dblink_conn->set_next_conn(temp); + LOG_TRACE("session succ to hold a dblink connection", KP(dblink_conn), K(sessid), K(tenant_id_), K(ret)); + } + } + } + return ret; +} + +int ObTenantDblinkKeeper::get_dblink_conn(uint32_t sessid, uint64_t dblink_id, + common::sqlclient::ObISQLConnection *&dblink_conn) +{ + int ret = OB_SUCCESS; + dblink_conn = NULL; + ObArray *dblink_conn_array = NULL; + int64_t value = 0; + obsys::ObRLockGuard wg(lock_); + if (!dblink_conn_map_.created()) { + ret = OB_NOT_INIT; + LOG_WARN("dblink_conn_map_ is not inited", K(ret), K(tenant_id_), K(sessid)); + } else if (OB_FAIL(dblink_conn_map_.get_refactored(sessid, value))) { + if (OB_HASH_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get connection", K(ret), K(sessid)); + } + } else if (0 == value) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("value is NULL", K(ret), K(value), K(sessid)); + } else { + common::sqlclient::ObISQLConnection *connection = reinterpret_cast(value); + common::sqlclient::ObISQLConnection *temp_conn = NULL; + while (OB_NOT_NULL(connection)) { + if (dblink_id == connection->get_dblink_id()) { + temp_conn = connection; + break; + } + connection = connection->get_next_conn(); + } + if (OB_SUCC(ret) && OB_NOT_NULL(temp_conn)) { + if (OB_SUCCESS != temp_conn->ping()) { + ret = OB_ERR_DBLINK_SESSION_KILLED; + LOG_WARN("connection is invalid", K(ret), K(temp_conn->usable()), KP(temp_conn), K(sessid), K(tenant_id_)); + } else { + dblink_conn = temp_conn; + dblink_conn->dblink_rlock(); + } + } + LOG_TRACE("session get a dblink connection", K(ret), K(dblink_id), K(tenant_id_), KP(dblink_conn), K(sessid)); + } + return ret; +} + +int ObTenantDblinkKeeper::init(uint64_t tenant_id) +{ + static int SESSION_COUNT = 1024; + int ret = OB_SUCCESS; + tenant_id_ = tenant_id; + ObMemAttr attr(tenant_id, "DblinkKeeperBkt"); + if (OB_FAIL(dblink_conn_map_.create(SESSION_COUNT, attr, attr))) { + LOG_WARN("fail init pool map", K(ret), K(tenant_id)); + } + return ret; +} + +int ObTenantDblinkKeeper::mtl_new(ObTenantDblinkKeeper *&dblink_keeper) +{ + int ret = OB_SUCCESS; + uint64_t tenant_id = tenant_id = get_current_tenant_id_for_dblink(); + if (OB_INVALID_ID == tenant_id) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid tenant id", K(ret), KP(get_current_tenant_id_for_dblink)); + } else if (FALSE_IT(dblink_keeper = OB_NEW(ObTenantDblinkKeeper, ObMemAttr(tenant_id, "DblinkKeeper")))) { + } else if (OB_ISNULL(dblink_keeper)) { + ret = common::OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc meme", K(ret)); + } + return ret; +} + +int ObTenantDblinkKeeper::mtl_init(ObTenantDblinkKeeper *&dblink_keeper) +{ + int ret = OB_SUCCESS; + uint64_t tenant_id = tenant_id = get_current_tenant_id_for_dblink(); + if (OB_INVALID_ID == tenant_id) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid tenant id", K(ret), KP(get_current_tenant_id_for_dblink)); + } else if (OB_ISNULL(dblink_keeper)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else { + dblink_keeper->init(tenant_id); + LOG_TRACE("init dblink_keeper", K(tenant_id), KP(dblink_keeper), K(ret)); + } + return ret; +} + +void ObTenantDblinkKeeper::mtl_destroy(ObTenantDblinkKeeper *&dblink_keeper) +{ + common::ob_delete(dblink_keeper); + dblink_keeper = nullptr; +} + +int ObTenantDblinkKeeper::destroy() +{ + int ret = OB_SUCCESS; + CleanDblinkArrayFunc clean_dblink_func; + if (OB_FAIL(dblink_conn_map_.foreach_refactored(clean_dblink_func))) { + LOG_WARN("failed to do foreach", K(ret)); + } else { + dblink_conn_map_.destroy(); + tenant_id_ = OB_INVALID_ID; + } + return ret; +} + +int ObTenantDblinkKeeper::CleanDblinkArrayFunc::operator() (common::hash::HashMapPair &kv) +{ + int ret = OB_SUCCESS; + common::sqlclient::ObISQLConnection *connection = reinterpret_cast(kv.second); + while (OB_SUCC(ret) && OB_NOT_NULL(connection)) { + common::sqlclient::ObISQLConnection *next = connection->get_next_conn(); + connection->set_reverse_link_creadentials(false); + common::sqlclient::ObCommonServerConnectionPool * server_conn_pool = NULL; + server_conn_pool = connection->get_common_server_pool(); + uint32_t sessid = connection->get_sessid(); + if (NULL == server_conn_pool) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("server_conn_pool of dblink connection is NULL", K(sessid), KP(connection), K(ret)); + } else { + if (OB_FAIL(server_conn_pool->release(connection, false))) { + LOG_WARN("session failed to release dblink connection", K(sessid), KP(connection), K(ret)); + } else { + LOG_TRACE("session succ to release dblink connection", K(sessid), KP(connection), K(ret)); + } + } + connection = next; + } + if (OB_SUCC(ret)) { + kv.second = 0; + } + return ret; +} +#endif + +} // end namespace sqlclient } // end namespace common } // end namespace oceanbase diff --git a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h index 872900b274..d7055b6f1b 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h +++ b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h @@ -14,9 +14,11 @@ #define OBDBLINKERROR_H #include "lib/utility/ob_edit_distance.h" #include "lib/ob_errno.h" +#include "lib/mysqlclient/ob_isql_connection.h" extern bool get_dblink_reuse_connection_cfg(); extern bool get_enable_dblink_cfg(); +extern uint64_t get_current_tenant_id_for_dblink(); namespace oceanbase { @@ -56,6 +58,44 @@ public: int &ob_errno); }; + +#ifdef OB_BUILD_DBLINK +class ObTenantDblinkKeeper +{ +public: + class CleanDblinkArrayFunc + { + public: + CleanDblinkArrayFunc() {} + virtual ~CleanDblinkArrayFunc() = default; + int operator()(common::hash::HashMapPair &kv); + }; +public: + static int mtl_new(ObTenantDblinkKeeper *&dblink_keeper); + static int mtl_init(ObTenantDblinkKeeper *&dblink_keeper); + static void mtl_destroy(ObTenantDblinkKeeper *&dblink_keeper); +public: + ObTenantDblinkKeeper() + { + tenant_id_ = common::OB_INVALID_ID; + } + ~ObTenantDblinkKeeper() + { + destroy(); + } + int init(uint64_t tenant_id); + int set_dblink_conn(uint32_t sessid, common::sqlclient::ObISQLConnection *dblink_conn); + int get_dblink_conn(uint32_t sessid, uint64_t dblink_id, + common::sqlclient::ObISQLConnection *&dblink_conn); + int clean_dblink_conn(uint32_t sessid, bool force_disconnect); +private: + int destroy(); +private: + uint64_t tenant_id_; + obsys::ObRWLock lock_; + hash::ObHashMap dblink_conn_map_; +}; +#endif } // namespace sqlclient } // namespace common } // namespace oceanbase diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h index 2d35b02711..36b9105add 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h @@ -100,7 +100,8 @@ public: last_set_sql_mode_cstr_buf_size_(0), last_set_client_charset_cstr_(NULL), last_set_connection_charset_cstr_(NULL), - last_set_results_charset_cstr_(NULL) + last_set_results_charset_cstr_(NULL), + next_conn_(NULL) {} virtual ~ObISQLConnection() { allocator_.reset(); @@ -109,6 +110,7 @@ public: last_set_client_charset_cstr_ = NULL; last_set_connection_charset_cstr_ = NULL; last_set_results_charset_cstr_ = NULL; + next_conn_ = NULL; } // sql execute interface @@ -239,11 +241,13 @@ public: } if (param_ctx.set_client_charset_cstr_ != last_set_client_charset_cstr_ || param_ctx.set_connection_charset_cstr_ != last_set_connection_charset_cstr_ || - param_ctx.set_results_charset_cstr_ != last_set_results_charset_cstr_) { + param_ctx.set_results_charset_cstr_ != last_set_results_charset_cstr_ || + param_ctx.set_transaction_isolation_cstr_ != last_set_transaction_isolation_cstr_) { is_inited = false; last_set_client_charset_cstr_ = param_ctx.set_client_charset_cstr_; last_set_connection_charset_cstr_ = param_ctx.set_connection_charset_cstr_; last_set_results_charset_cstr_ = param_ctx.set_results_charset_cstr_; + last_set_transaction_isolation_cstr_ = param_ctx.set_transaction_isolation_cstr_; } return ret; } @@ -254,6 +258,12 @@ public: void set_usable(bool flag) { usable_ = flag; } bool usable() { return usable_; } virtual int ping() { return OB_SUCCESS; } + void dblink_rlock() { dblink_lock_.rlock()->lock(); } + void dblink_unrlock() { dblink_lock_.rlock()->unlock(); } + void dblink_wlock() { dblink_lock_.wlock()->lock(); } + void dblink_unwlock() { dblink_lock_.wlock()->unlock(); } + ObISQLConnection *get_next_conn() { return next_conn_; } + void set_next_conn(ObISQLConnection *conn) { next_conn_ = conn; } protected: bool oracle_mode_; bool is_inited_; // for oracle dblink, we have to init remote env with some sql @@ -268,7 +278,10 @@ protected: const char *last_set_client_charset_cstr_; const char *last_set_connection_charset_cstr_; const char *last_set_results_charset_cstr_; + const char *last_set_transaction_isolation_cstr_; common::ObArenaAllocator allocator_; + obsys::ObRWLock dblink_lock_; + ObISQLConnection *next_conn_; // used in dblink_conn_map_ }; } // end namespace sqlclient diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection_pool.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection_pool.h index 0fd2fb7201..0486a32764 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection_pool.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection_pool.h @@ -75,6 +75,7 @@ struct dblink_param_ctx{ const char *set_client_charset_cstr_; const char *set_connection_charset_cstr_; const char *set_results_charset_cstr_; + const char *set_transaction_isolation_cstr_; dblink_param_ctx() : charset_id_(static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID)), //utf8, deault value, don't modify it cause dblink pull meta need it ncharset_id_(static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID)), //utf8, deault value, don't modify it cause dblink pull meta need it @@ -87,7 +88,8 @@ struct dblink_param_ctx{ set_sql_mode_cstr_(NULL), set_client_charset_cstr_(NULL), set_connection_charset_cstr_(NULL), - set_results_charset_cstr_(NULL) + set_results_charset_cstr_(NULL), + set_transaction_isolation_cstr_(NULL) { } TO_STRING_KV(K_(charset_id), K_(ncharset_id), @@ -100,7 +102,8 @@ struct dblink_param_ctx{ K_(set_sql_mode_cstr), K_(set_client_charset_cstr), K_(set_connection_charset_cstr), - K_(set_results_charset_cstr)); + K_(set_results_charset_cstr), + K_(set_transaction_isolation_cstr)); }; class ObISQLConnectionPool diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp index 69afe27331..aed12be293 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp @@ -463,18 +463,21 @@ int ObDbLinkProxy::acquire_dblink(const dblink_param_ctx ¶m_ctx, ObISQLConne int ret = OB_SUCCESS; DISABLE_SQL_MEMLEAK_GUARD; ObISQLConnectionPool *dblink_pool = NULL; + ObISQLConnection * conn = NULL; if (!is_inited()) { ret = OB_NOT_INIT; LOG_WARN("dblink proxy not inited"); } else if (OB_FAIL(switch_dblink_conn_pool(param_ctx.link_type_, dblink_pool))) { LOG_WARN("failed to get dblink interface", K(ret), K(param_ctx)); - } else if (OB_FAIL(dblink_pool->acquire_dblink(param_ctx, dblink_conn))) { + } else if (OB_FAIL(dblink_pool->acquire_dblink(param_ctx, conn))) { LOG_WARN("acquire dblink failed", K(ret), K(param_ctx)); - } else if (OB_FAIL(prepare_enviroment(param_ctx, dblink_conn))) { + } else if (OB_FAIL(prepare_enviroment(param_ctx, conn))) { LOG_WARN("failed to prepare dblink env", K(ret)); } else { - dblink_conn->set_dblink_id(param_ctx.dblink_id_); - dblink_conn->set_dblink_driver_proto(param_ctx.link_type_); + conn->set_dblink_id(param_ctx.dblink_id_); + conn->set_dblink_driver_proto(param_ctx.link_type_); + conn->set_next_conn(NULL); + dblink_conn = conn; } return ret; } @@ -510,7 +513,8 @@ int ObDbLinkProxy::execute_init_sql(const sqlclient::dblink_param_ctx ¶m_ctx sql_ptr_type sql_ptr[] = {param_ctx.set_sql_mode_cstr_, param_ctx.set_client_charset_cstr_, param_ctx.set_connection_charset_cstr_, - param_ctx.set_results_charset_cstr_}; + param_ctx.set_results_charset_cstr_, + param_ctx.set_transaction_isolation_cstr_}; ObMySQLStatement stmt; ObMySQLConnection *mysql_conn = static_cast(dblink_conn); for (int i = 0; OB_SUCC(ret) && i < sizeof(sql_ptr) / sizeof(sql_ptr_type); ++i) { @@ -529,6 +533,7 @@ int ObDbLinkProxy::execute_init_sql(const sqlclient::dblink_param_ctx ¶m_ctx param_ctx.set_client_charset_cstr_, param_ctx.set_connection_charset_cstr_, param_ctx.set_results_charset_cstr_, + param_ctx.set_transaction_isolation_cstr_, "set nls_date_format='YYYY-MM-DD HH24:MI:SS'", "set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF'", "set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF TZR TZD'" @@ -543,8 +548,6 @@ int ObDbLinkProxy::execute_init_sql(const sqlclient::dblink_param_ctx ¶m_ctx LOG_WARN("create statement failed", K(ret), K(param_ctx)); } else if (OB_FAIL(stmt.execute_update())) { LOG_WARN("execute sql failed", K(ret), K(param_ctx)); - } else { - // do nothing } } } @@ -582,9 +585,13 @@ int ObDbLinkProxy::release_dblink(/*uint64_t dblink_id,*/ DblinkDriverProto dbli int ret = OB_SUCCESS; DISABLE_SQL_MEMLEAK_GUARD; ObISQLConnectionPool *dblink_pool = NULL; - if (!is_inited()) { + if (OB_ISNULL(dblink_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexcepted null ptr", K(ret)); + } else if (FALSE_IT(dblink_conn->set_next_conn(NULL))) { + } else if (!is_inited()) { ret = OB_NOT_INIT; - LOG_WARN("dblink proxy not inited"); + LOG_WARN("dblink proxy not inited", K(ret)); } else if (OB_FAIL(switch_dblink_conn_pool(dblink_type, dblink_pool))) { LOG_WARN("failed to get dblink interface", K(ret)); } else if (OB_FAIL(dblink_pool->release_dblink(dblink_conn))) { diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp index af2cd08ac0..18d9934430 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp @@ -162,7 +162,7 @@ ObMySQLResult *ObMySQLStatement::execute_query(bool enable_use_result) "err_msg", errmsg, K(ret), K(sql_str_)); } else { LOG_WARN("fail to query server", "host", stmt_->host, "port", stmt_->port, K(conn_->get_sessid()), - "err_msg", errmsg, K(ret), K(STRLEN(sql_str_)), K(sql_str_)); + "err_msg", errmsg, K(ret), K(STRLEN(sql_str_)), K(sql_str_), K(lbt())); } if (OB_SUCCESS == ret) { ret = OB_ERR_SQL_CLIENT; diff --git a/deps/oblib/src/lib/mysqlclient/ob_tenant_oci_envs.h b/deps/oblib/src/lib/mysqlclient/ob_tenant_oci_envs.h index e1c201f520..a06d0ac108 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_tenant_oci_envs.h +++ b/deps/oblib/src/lib/mysqlclient/ob_tenant_oci_envs.h @@ -26,9 +26,16 @@ public: static int mtl_init(ObTenantOciEnvs *&tenant_oci_envs) { return OB_SUCCESS; } static void mtl_destroy(ObTenantOciEnvs *&tenant_oci_envs) { } }; +class ObTenantDblinkKeeper +{ +public: + static int mtl_new(ObTenantDblinkKeeper *&dblink_keeper) { return OB_SUCCESS; } + static int mtl_init(ObTenantDblinkKeeper *&dblink_keeper) { return OB_SUCCESS; } + static void mtl_destroy(ObTenantDblinkKeeper *&dblink_keeper) { } +}; #endif } //sqlclient } // namespace common } // namespace oceanbase -#endif //OBTENANOCIENVS_H +#endif //OBTENANOCIENVS_H \ No newline at end of file diff --git a/src/observer/omt/ob_multi_tenant.cpp b/src/observer/omt/ob_multi_tenant.cpp index 7daaf842fa..5b2a4f69c7 100644 --- a/src/observer/omt/ob_multi_tenant.cpp +++ b/src/observer/omt/ob_multi_tenant.cpp @@ -130,6 +130,7 @@ #endif #ifdef OB_BUILD_DBLINK #include "lib/oracleclient/ob_oci_environment.h" +#include "lib/mysqlclient/ob_dblink_error_trans.h" #endif #include "lib/mysqlclient/ob_tenant_oci_envs.h" #include "sql/udr/ob_udr_mgr.h" @@ -573,6 +574,9 @@ int ObMultiTenant::init(ObAddr myaddr, MTL_BIND2(mtl_new_default, storage::ObTabletMemtableMgrPool::mtl_init, nullptr, nullptr, nullptr, mtl_destroy_default); MTL_BIND2(mtl_new_default, rootserver::ObMViewMaintenanceService::mtl_init, mtl_start_default, mtl_stop_default, mtl_wait_default, mtl_destroy_default); MTL_BIND2(mtl_new_default, ObCheckpointDiagnoseMgr::mtl_init, nullptr, nullptr, nullptr, mtl_destroy_default); +#ifdef OB_BUILD_DBLINK + MTL_BIND2(common::sqlclient::ObTenantDblinkKeeper::mtl_new, common::sqlclient::ObTenantDblinkKeeper::mtl_init, nullptr, nullptr, nullptr, common::sqlclient::ObTenantDblinkKeeper::mtl_destroy); +#endif } if (OB_SUCC(ret)) { diff --git a/src/share/rc/ob_tenant_base.h b/src/share/rc/ob_tenant_base.h index 5f2e820be2..8cce8d9536 100755 --- a/src/share/rc/ob_tenant_base.h +++ b/src/share/rc/ob_tenant_base.h @@ -24,6 +24,7 @@ #include "share/ob_tenant_role.h"//ObTenantRole #ifdef OB_BUILD_DBLINK #include "lib/oracleclient/ob_oci_environment.h" +#include "lib/mysqlclient/ob_dblink_error_trans.h" #endif #include "lib/mysqlclient/ob_tenant_oci_envs.h" namespace oceanbase @@ -354,7 +355,8 @@ using ObTableScanIteratorObjPool = common::ObServerObjectPoolcreate_dblink_pool(param_ctx, dblink_schema->get_host_addr(), @@ -9054,7 +9059,6 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(dblink_param_ctx ¶m_ctx, } else { LOG_DEBUG("succ to read table meta by reverse_link"); } - } else if (FALSE_IT(param_ctx.sessid_ = session_info->get_sessid())) { } else if (OB_FAIL(dblink_proxy_->acquire_dblink(param_ctx, dblink_conn))) { LOG_WARN("failed to acquire dblink", K(ret), K(param_ctx)); diff --git a/src/sql/code_generator/ob_static_engine_cg.cpp b/src/sql/code_generator/ob_static_engine_cg.cpp index ce255c1c74..71b45984a7 100644 --- a/src/sql/code_generator/ob_static_engine_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_cg.cpp @@ -6846,7 +6846,23 @@ int ObStaticEngineCG::generate_spec(ObLogLinkScan &op, ObLinkScanSpec &spec, con { UNUSED(in_root_job); int ret = OB_SUCCESS; - if (OB_FAIL(op.gen_link_stmt_param_infos())) { + const ObLogPlan *log_plan = NULL; + ObExecContext *exec_ctx = NULL; + ObPhysicalPlanCtx *plan_ctx = NULL; + ObSQLSessionInfo *my_session = NULL; + common::ObArenaAllocator allocator; + common::sqlclient::dblink_param_ctx dblink_param_ctx; + if (OB_ISNULL(log_plan = op.get_plan()) || + OB_ISNULL(my_session = log_plan->get_optimizer_context().get_session_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexcepted null ptr", KP(log_plan), KP(my_session), K(ret)); + } else if (OB_ISNULL(exec_ctx = log_plan->get_optimizer_context().get_exec_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexcepted null ptr", K(ret)); + } else if (OB_ISNULL(plan_ctx = exec_ctx->get_physical_plan_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("plan context is null"); + } else if (OB_FAIL(op.gen_link_stmt_param_infos())) { LOG_WARN("failed to generate link stmt", K(ret)); } else if (OB_FAIL(spec.set_param_infos(op.get_param_infos()))) { LOG_WARN("failed to set param infos", K(ret)); @@ -6854,16 +6870,34 @@ int ObStaticEngineCG::generate_spec(ObLogLinkScan &op, ObLinkScanSpec &spec, con LOG_WARN("failed to set stmt fmt", K(ret)); } else if (OB_FAIL(spec.select_exprs_.init(op.get_select_exprs().count()))) { LOG_WARN("init fixed array failed", K(ret), K(op.get_select_exprs().count())); - } else if (OB_ISNULL(op.get_plan())) { + } else if (OB_ISNULL(log_plan->get_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null ptr", K(ret)); - } else if (OB_ISNULL(op.get_plan()->get_stmt())) { - ret = OB_ERR_UNEXPECTED; + } else if (OB_ISNULL(phy_plan_)) { LOG_WARN("unexpected null ptr", K(ret)); + } else if (lib::is_oracle_mode() && + 0 != op.get_dblink_id() && + OB_INVALID_ID != op.get_dblink_id() && + OB_FAIL(plan_ctx->keep_dblink_id(op.get_dblink_id()))) { + LOG_WARN("failed to keep dblink id in phy_plan", K(ret), K(op.get_dblink_id()), K(phy_plan_)); + } else if (lib::is_oracle_mode() && + OB_FAIL(ObDblinkService::get_local_session_vars(my_session, allocator, dblink_param_ctx))) { + LOG_WARN("failed to get local session vars", K(ret)); } else { spec.has_for_update_ = op.get_plan()->get_stmt()->has_for_update(); spec.is_reverse_link_ = op.get_reverse_link(); spec.dblink_id_ = op.get_dblink_id(); + phy_plan_->set_has_link_sfd(spec.has_for_update_); + plan_ctx->set_tx_id(log_plan->get_optimizer_context().get_global_hint().dblink_hints_.tx_id_); + plan_ctx->set_tm_sessid(log_plan->get_optimizer_context().get_global_hint().dblink_hints_.tm_sessid_); + plan_ctx->set_hint_xa_trans_stop_check_lock(log_plan->get_optimizer_context().get_global_hint().dblink_hints_.hint_xa_trans_stop_check_lock_); + plan_ctx->set_main_xa_trans_branch(!spec.is_reverse_link_ && + 0 == plan_ctx->get_tx_id() && // ensure this sql is not sent by reverse link + 0 == plan_ctx->get_tm_sessid() && // ensure this sql is not sent by reverse link + ((my_session->is_in_transaction() && OB_NOT_NULL(my_session->get_tx_desc())) || + ObDblinkService::SET_ISOLATION_LEVEL_SERIALIZABLE == dblink_param_ctx.set_transaction_isolation_cstr_ || + phy_plan_->has_link_sfd())); + LOG_TRACE("link set plan_ctx properties", KP(plan_ctx), K(plan_ctx->get_hint_xa_trans_stop_check_lock()), K(!spec.is_reverse_link_), K(plan_ctx->get_main_xa_trans_branch()), K(plan_ctx->get_tx_id()), K(plan_ctx->get_tm_sessid()), K(my_session->is_in_transaction()), KP(my_session->get_tx_desc()), K(phy_plan_->has_link_sfd()), K(dblink_param_ctx.set_transaction_isolation_cstr_)); for (int64_t i = 0; OB_SUCC(ret) && i < op.get_select_exprs().count(); ++i) { ObExpr *rt_expr = nullptr; const ObRawExpr* select_expr = op.get_select_exprs().at(i); @@ -6877,6 +6911,7 @@ int ObStaticEngineCG::generate_spec(ObLogLinkScan &op, ObLinkScanSpec &spec, con } } } + allocator.reset(); return ret; } @@ -6884,17 +6919,43 @@ int ObStaticEngineCG::generate_spec(ObLogLinkDml &op, ObLinkDmlSpec &spec, const { UNUSED(in_root_job); int ret = OB_SUCCESS; - if (OB_FAIL(op.gen_link_stmt_param_infos())) { + const ObLogPlan *log_plan = NULL; + ObExecContext *exec_ctx = NULL; + ObPhysicalPlanCtx *plan_ctx = NULL; + if (OB_ISNULL(log_plan = op.get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexcepted null ptr", K(ret)); + } else if (OB_ISNULL(exec_ctx = log_plan->get_optimizer_context().get_exec_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexcepted null ptr", K(ret)); + } else if (OB_ISNULL(plan_ctx = exec_ctx->get_physical_plan_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("plan context is null"); + } else if (OB_FAIL(op.gen_link_stmt_param_infos())) { LOG_WARN("failed to generate link stmt", K(ret)); } else if (OB_FAIL(spec.set_param_infos(op.get_param_infos()))) { LOG_WARN("failed to set param infos", K(ret)); } else if (OB_FAIL(spec.set_stmt_fmt(op.get_stmt_fmt_buf(), op.get_stmt_fmt_len()))) { LOG_WARN("failed to set stmt fmt", K(ret)); + } else if (lib::is_oracle_mode() && + 0 != op.get_dblink_id() && + OB_INVALID_ID != op.get_dblink_id() && + OB_FAIL(plan_ctx->keep_dblink_id(op.get_dblink_id()))) { + LOG_WARN("failed to keep dblink id in phy_plan", K(ret), K(op.get_dblink_id()), K(phy_plan_)); } else { - spec.is_reverse_link_ = op.get_reverse_link(); - spec.dblink_id_ = op.get_dblink_id(); - spec.plan_->set_returning(false); - spec.plan_->need_drive_dml_query_ = true; + for (int64_t i = 0; lib::is_oracle_mode() && OB_SUCC(ret) && i < op.get_related_dblink_ids().count(); ++i) { + if (OB_FAIL(plan_ctx->keep_dblink_id(op.get_related_dblink_ids().at(i)))) { + LOG_WARN("failed to keep dblink id in phy_plan", K(ret), K(op.get_related_dblink_ids().at(i)), K(i), K(phy_plan_)); + } + } + if (OB_SUCC(ret)) { + spec.is_reverse_link_ = op.get_reverse_link(); + spec.dblink_id_ = op.get_dblink_id(); + spec.plan_->set_returning(false); + spec.plan_->need_drive_dml_query_ = true; + plan_ctx->set_main_xa_trans_branch(true); + LOG_TRACE("link set plan_ctx properties", KP(plan_ctx), K(ret)); + } } return ret; } @@ -7752,8 +7813,6 @@ int ObStaticEngineCG::set_other_properties(const ObLogPlan &log_plan, ObPhysical } else { phy_plan.set_need_param(param_opt==ObParamOption::FORCE); } - phy_plan.tx_id_ = log_plan.get_optimizer_context().get_global_hint().tx_id_; - phy_plan.tm_sessid_ = log_plan.get_optimizer_context().get_global_hint().tm_sessid_; } if (OB_SUCC(ret)) { diff --git a/src/sql/dblink/ob_dblink_utils.cpp b/src/sql/dblink/ob_dblink_utils.cpp index f180665b98..d7d380f2d5 100644 --- a/src/sql/dblink/ob_dblink_utils.cpp +++ b/src/sql/dblink/ob_dblink_utils.cpp @@ -19,6 +19,7 @@ #include "sql/session/ob_sql_session_info.h" #include "common/ob_smart_call.h" #include "common/object/ob_object.h" +#include "lib/mysqlclient/ob_dblink_error_trans.h" #ifdef OB_BUILD_DBLINK #include "observer/omt/ob_multi_tenant.h" #include "share/rc/ob_tenant_base.h" @@ -43,7 +44,7 @@ bool get_enable_dblink_cfg() return GCONF.enable_dblink; } -uint64_t ObDblinkService::get_current_tenant_id() +uint64_t get_current_tenant_id_for_dblink() { return MTL_ID(); } @@ -56,13 +57,86 @@ oceanbase::common::sqlclient::ObTenantOciEnvs * ObDblinkService::get_tenant_oci_ int ObDblinkService::init_oci_envs_func_ptr() { int ret = common::OB_SUCCESS; - OciEnvironment::get_tenant_id_ = get_current_tenant_id; OciEnvironment::get_tenant_oci_envs_ = get_tenant_oci_envs; return ret; } bool g_dblink_oci_func_ptr_inited = ObDblinkService::init_oci_envs_func_ptr(); #endif + +const char * ObDblinkService::SET_ISOLATION_LEVEL_READ_COMMITTED = "ALTER SESSION SET ISOLATION_LEVEL = READ COMMITTED"; +const char * ObDblinkService::SET_ISOLATION_LEVEL_REPEATABLE_READ = "ALTER SESSION SET ISOLATION_LEVEL = REPEATABLE READ"; +const char * ObDblinkService::SET_ISOLATION_LEVEL_SERIALIZABLE = "ALTER SESSION SET ISOLATION_LEVEL = SERIALIZABLE"; +const char * ObDblinkService::SET_ISOLATION_LEVEL_READ_COMMITTED_MYSQL_MODE = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"; +const char * ObDblinkService::SET_ISOLATION_LEVEL_REPEATABLE_READ_MYSQL_MODE = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"; +const char * ObDblinkService::SET_ISOLATION_LEVEL_SERIALIZABLE_MYSQL_MODE = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"; +const char * ObDblinkService::SET_RESULTS_CHARSET_NULL = "SET CHARACTER_SET_RESULTS = NULL"; +const char * ObDblinkService::SET_CLIENT_CHARSET_UTF8MB4 = "SET CHARACTER_SET_CLIENT = UTF8MB4"; +const char * ObDblinkService::SET_CLIENT_CHARSET_GBK = "SET CHARACTER_SET_CLIENT = GBK"; +const char * ObDblinkService::SET_CLIENT_CHARSET_BINARY = "SET CHARACTER_SET_CLIENT = BINARY"; +const char * ObDblinkService::SET_CONNECTION_CHARSET_UTF8MB4 = "SET CHARACTER_SET_CONNECTION = UTF8MB4"; +const char * ObDblinkService::SET_CONNECTION_CHARSET_GBK = "SET CHARACTER_SET_CONNECTION = GBK"; +const char * ObDblinkService::SET_CONNECTION_CHARSET_BINARY = "SET CHARACTER_SET_CONNECTION = BINARY"; +const char * ObDblinkService::SET_RESULTS_CHARSET_UTF8MB4 = "SET CHARACTER_SET_RESULTS = UTF8MB4"; +const char * ObDblinkService::SET_RESULTS_CHARSET_GBK = "SET CHARACTER_SET_RESULTS = GBK"; +const char * ObDblinkService::SET_RESULTS_CHARSET_BINARY = "SET CHARACTER_SET_RESULTS = BINARY"; + +int ObDblinkService::get_charset_id(ObSQLSessionInfo *session_info, + uint16_t &charset_id, + uint16_t &ncharset_id) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(session_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null session info", K(ret)); + } else { + ObCollationType coll_type = session_info->get_nls_collation(); + ObCollationType ncoll_type = session_info->get_nls_collation_nation(); + ObCharsetType cs_type = ObCharset::charset_type_by_coll(coll_type); + ObCharsetType ncs_type = ObCharset::charset_type_by_coll(ncoll_type); + if (CHARSET_INVALID == cs_type || CHARSET_INVALID == ncs_type) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get charset id", K(ret), K(coll_type)); + } else { + charset_id = static_cast(ObCharset::charset_type_to_ora_charset_id(cs_type)); + ncharset_id = static_cast(ObCharset::charset_type_to_ora_charset_id(ncs_type)); + LOG_DEBUG("get charset id", K(ret), K(charset_id), K(ncharset_id), + K(cs_type), K(ncs_type), K(coll_type), K(ncoll_type)); + } + } + return ret; +} + +int ObDblinkService::init_dblink_param_ctx(common::sqlclient::dblink_param_ctx ¶m_ctx, + sql::ObSQLSessionInfo *session_info, + ObIAllocator &allocator, + uint64_t dblink_id, + common::sqlclient::DblinkDriverProto link_type, + common::sqlclient::DblinkPoolType pool_type) +{ + int ret = OB_SUCCESS; + uint16_t charset_id = 0; + uint16_t ncharset_id = 0; + if (OB_ISNULL(session_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(get_charset_id(session_info, charset_id, ncharset_id))) { + LOG_WARN("failed to get session charset id", K(ret), K(dblink_id)); + } else if (OB_FAIL(get_local_session_vars(session_info, allocator, param_ctx))) { + LOG_WARN("failed to get local session vars", K(ret), K(dblink_id)); + } else { + param_ctx.charset_id_ = charset_id; + param_ctx.ncharset_id_ = ncharset_id; + param_ctx.pool_type_ = pool_type; + param_ctx.tenant_id_ = session_info->get_effective_tenant_id(); + param_ctx.sessid_ = session_info->get_sessid(); + param_ctx.sql_request_level_ = session_info->get_next_sql_request_level(); + param_ctx.dblink_id_ = dblink_id; + param_ctx.link_type_ = link_type; + } + return ret; +} + int ObDblinkService::check_lob_in_result(common::sqlclient::ObMySQLResult *result, bool &have_lob) { int ret = OB_SUCCESS; @@ -159,6 +233,33 @@ int ObDblinkService::get_set_sql_mode_cstr(sql::ObSQLSessionInfo *session_info, return ret; } +int ObDblinkService::get_set_transaction_isolation_cstr(sql::ObSQLSessionInfo *session_info, + const char *&set_isolation_level) +{ + int ret = OB_SUCCESS; + common::ObString val; + bool is_oracle_mode = lib::is_oracle_mode(); + if (OB_ISNULL(session_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(session_info->get_sys_variable(share::SYS_VAR_TRANSACTION_ISOLATION, val))) { + LOG_WARN("failed to get transaction isolation", K(ret)); + //} else if (0 == val.compare("UNCOMMITTED")) { + // set_isolation_level = ObDblinkService::SET_ISOLATION_LEVEL_UNCOMMITTED; + } else if (0 == val.compare("READ-COMMITTED")) { + set_isolation_level = is_oracle_mode ? ObDblinkService::SET_ISOLATION_LEVEL_READ_COMMITTED : ObDblinkService::SET_ISOLATION_LEVEL_READ_COMMITTED_MYSQL_MODE; + } else if (0 == val.compare("REPEATABLE-READ")) { + set_isolation_level = is_oracle_mode ? ObDblinkService::SET_ISOLATION_LEVEL_REPEATABLE_READ : ObDblinkService::SET_ISOLATION_LEVEL_REPEATABLE_READ_MYSQL_MODE; + } else if (0 == val.compare("SERIALIZABLE")) { + set_isolation_level = is_oracle_mode ? ObDblinkService::SET_ISOLATION_LEVEL_SERIALIZABLE : ObDblinkService::SET_ISOLATION_LEVEL_SERIALIZABLE_MYSQL_MODE; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected transaction isolation value", K(ret), K(val)); + } + LOG_TRACE("dblink get isolation level from session", K(ret), K(session_info), K(set_isolation_level)); + return ret; +} + int ObDblinkService::get_set_names_cstr(sql::ObSQLSessionInfo *session_info, const char *&set_client_charset, const char *&set_connection_charset, @@ -183,13 +284,13 @@ int ObDblinkService::get_set_names_cstr(sql::ObSQLSessionInfo *session_info, } else { switch(ObCharset::charset_type_by_coll(ObCollationType(client))) { case ObCharsetType::CHARSET_UTF8MB4: - set_client_charset = "set character_set_client = utf8mb4"; + set_client_charset = ObDblinkService::SET_CLIENT_CHARSET_UTF8MB4; break; case ObCharsetType::CHARSET_GBK: - set_client_charset = "set character_set_client = gbk"; + set_client_charset = ObDblinkService::SET_CLIENT_CHARSET_GBK; break; case ObCharsetType::CHARSET_BINARY: - set_client_charset = "set character_set_client = binary"; + set_client_charset = ObDblinkService::SET_CLIENT_CHARSET_BINARY; break; default: // do nothing @@ -197,13 +298,13 @@ int ObDblinkService::get_set_names_cstr(sql::ObSQLSessionInfo *session_info, } switch(ObCharset::charset_type_by_coll(ObCollationType(connection))) { case ObCharsetType::CHARSET_UTF8MB4: - set_connection_charset = "set character_set_connection = utf8mb4"; + set_connection_charset = ObDblinkService::SET_CONNECTION_CHARSET_UTF8MB4; break; case ObCharsetType::CHARSET_GBK: - set_connection_charset = "set character_set_connection = gbk"; + set_connection_charset = ObDblinkService::SET_CONNECTION_CHARSET_GBK; break; case ObCharsetType::CHARSET_BINARY: - set_connection_charset = "set character_set_connection = binary"; + set_connection_charset = ObDblinkService::SET_CONNECTION_CHARSET_BINARY; break; default: // do nothing @@ -211,13 +312,13 @@ int ObDblinkService::get_set_names_cstr(sql::ObSQLSessionInfo *session_info, } switch(ObCharset::charset_type_by_coll(ObCollationType(results))) { case ObCharsetType::CHARSET_UTF8MB4: - set_results_charset = "set character_set_results = utf8mb4"; + set_results_charset = ObDblinkService::SET_RESULTS_CHARSET_UTF8MB4; break; case ObCharsetType::CHARSET_GBK: - set_results_charset = "set character_set_results = gbk"; + set_results_charset = ObDblinkService::SET_RESULTS_CHARSET_GBK; break; case ObCharsetType::CHARSET_BINARY: - set_results_charset = "set character_set_results = binary"; + set_results_charset = ObDblinkService::SET_RESULTS_CHARSET_BINARY; break; default: // do nothing @@ -239,6 +340,9 @@ int ObDblinkService::get_local_session_vars(sql::ObSQLSessionInfo *session_info, param_ctx.set_connection_charset_cstr_, param_ctx.set_results_charset_cstr_))) { LOG_WARN("failed to get set_names_cstr", K(ret)); + } else if (OB_FAIL(get_set_transaction_isolation_cstr(session_info, + param_ctx.set_transaction_isolation_cstr_))) { + LOG_WARN("failed to get set_transaction_isolation_cstr", K(ret)); } return ret; } @@ -434,7 +538,7 @@ int ObReverseLink::close() return ret; } -int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink) +int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool enable_check_any_dblink) { int ret = OB_SUCCESS; ObArray child_stmts; @@ -445,7 +549,7 @@ int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &h } else if (OB_FAIL(stmt->get_sequence_exprs(seq_exprs))) { LOG_WARN("failed to get sequence exprs", K(ret)); } - for (int64_t i = 0; OB_SUCC(ret) && !has && i < seq_exprs.count(); ++i) { + for (int64_t i = 0; OB_SUCC(ret) && enable_check_any_dblink && !has && i < seq_exprs.count(); ++i) { ObRawExpr *expr = seq_exprs.at(i); if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; @@ -462,16 +566,16 @@ int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &h if (OB_ISNULL(table_item)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get null ptr", K(ret)); - } else if (has_any_dblink && (table_item->is_reverse_link_ || OB_INVALID_ID != table_item->dblink_id_)) { + } else if (enable_check_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_) { + } else if (!enable_check_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_or_any_dblink(table_item->ref_query_, has, has_any_dblink)))) { + if (OB_FAIL(SMART_CALL(has_reverse_link_or_any_dblink(table_item->ref_query_, has, enable_check_any_dblink)))) { LOG_WARN("failed to exec has_reverse_link", K(ret)); } else if (has) { break; @@ -487,7 +591,7 @@ int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &h 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_or_any_dblink(child_stmt, has, has_any_dblink)))) { + } else if (OB_FAIL(SMART_CALL(has_reverse_link_or_any_dblink(child_stmt, has, enable_check_any_dblink)))) { LOG_WARN("failed to exec has_reverse_link", K(ret)); } else if (has) { break; @@ -498,6 +602,65 @@ int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &h return ret; } +int ObDblinkUtils::gather_dblink_id(const ObDMLStmt *stmt, ObIArray &dblink_id_array) +{ + int ret = OB_SUCCESS; + ObArray child_stmts; + ObSEArray seq_exprs; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null stmt", K(ret)); + } else if (OB_FAIL(stmt->get_sequence_exprs(seq_exprs))) { + LOG_WARN("failed to get sequence exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < seq_exprs.count(); ++i) { + ObRawExpr *expr = seq_exprs.at(i); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null expr", K(ret)); + } else { + ObSequenceRawExpr *seq_expr = static_cast(expr); + int64_t dblink_id = seq_expr->get_dblink_id(); + if (OB_INVALID_ID != dblink_id && + 0 != dblink_id && + OB_FAIL(add_var_to_array_no_dup(dblink_id_array, dblink_id))) { + LOG_WARN("failed to add dblink id to array", K(ret), K(dblink_id)); + } + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_table_items().count(); ++i) { + const TableItem *table_item = stmt->get_table_items().at(i); + if (OB_ISNULL(table_item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null ptr", K(ret)); + } else if (OB_INVALID_ID != table_item->dblink_id_ && + 0 != table_item->dblink_id_ && + OB_FAIL(add_var_to_array_no_dup(dblink_id_array, table_item->dblink_id_))) { + LOG_WARN("failed to add dblink id to array", K(ret), K(table_item->dblink_id_)); + } else if (table_item->is_temp_table()) { + if (OB_FAIL(SMART_CALL(gather_dblink_id(table_item->ref_query_, dblink_id_array)))) { + LOG_WARN("failed to exec gather_dblink_id", K(ret)); + } + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts", K(ret), KP(stmt)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + ObDMLStmt *child_stmt = child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null ptr", K(ret)); + } else if (OB_FAIL(SMART_CALL(gather_dblink_id(child_stmt, dblink_id_array)))) { + LOG_WARN("failed to exec gather_dblink_id", K(ret)); + } + } + } + } + return ret; +} + /** The meaning of register is to record the ObServerConnectionPool used by this session in the array through pointers. The pointer values stored in this array are unique to each other. @@ -549,85 +712,93 @@ int ObDblinkCtxInSession::free_dblink_conn_pool() return ret; } -int ObDblinkCtxInSession::get_dblink_conn(uint64_t dblink_id, common::sqlclient::ObISQLConnection *&dblink_conn) +/** + * after call get_dblink_conn , you need call revert_dblink_conn to free rlock which is in connection +*/ +int ObDblinkCtxInSession::get_dblink_conn(uint64_t dblink_id, common::sqlclient::ObISQLConnection *&dblink_conn, uint32_t tm_sessid) { int ret = OB_SUCCESS; dblink_conn = NULL; +#ifdef OB_BUILD_DBLINK + uint32_t sessid = 0; common::sqlclient::ObISQLConnection *conn =NULL; - if (OB_ISNULL(session_info_)) { + oceanbase::common::sqlclient::ObTenantDblinkKeeper *tenant_dblink_keeper = MTL(oceanbase::common::sqlclient::ObTenantDblinkKeeper*); + if (OB_ISNULL(session_info_) || OB_ISNULL(tenant_dblink_keeper)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexcepted null ptr", K(ret)); - } - for (int64_t i = 0; OB_SUCC(ret) && i < dblink_conn_holder_array_.count(); ++i) { - conn = reinterpret_cast(dblink_conn_holder_array_.at(i)); - if (OB_UNLIKELY(NULL == conn)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("connection in dblink_conn_holder_array_ is NULL", K(session_info_->get_sessid()), K(i), K(ret)); - } else if (dblink_id == conn->get_dblink_id()) { - dblink_conn = conn; - break; - } - } - if (OB_SUCC(ret) && OB_NOT_NULL(dblink_conn) && - (OB_SUCCESS != dblink_conn->ping())) { + LOG_WARN("unexcepted null ptr", K(ret), KP(session_info_), KP(tenant_dblink_keeper)); + } else if (FALSE_IT(sessid = session_info_->get_sessid())) { + } else if (OB_FAIL(tenant_dblink_keeper->get_dblink_conn((0 != tm_sessid) ? tm_sessid : sessid, dblink_id, conn))) { + LOG_WARN("failed to get dblink conn", K(ret), K(tm_sessid), K(sessid), K(dblink_id), KP(tenant_dblink_keeper)); + } else if (OB_ISNULL(conn)) { + // do nothing + } else if (OB_SUCCESS != (conn->ping())) { ret = OB_ERR_DBLINK_SESSION_KILLED; LOG_WARN("connection is invalid", K(ret), K(dblink_conn->usable()), KP(dblink_conn)); + } else { + dblink_conn = conn; } - LOG_TRACE("session get a dblink connection", K(ret), K(dblink_id), KP(dblink_conn), K(session_info_->get_sessid()), K(lbt())); + LOG_TRACE("get_dblink_conn", K(ret), K(dblink_id), KP(dblink_conn), K(tm_sessid), K(sessid), K(lbt())); +#endif + return ret; +} + +int ObDblinkCtxInSession::revert_dblink_conn(common::sqlclient::ObISQLConnection *&dblink_conn) +{ + int ret = OB_SUCCESS; +#ifdef OB_BUILD_DBLINK + if (OB_ISNULL(dblink_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else { + dblink_conn->dblink_unrlock(); + } +#endif return ret; } int ObDblinkCtxInSession::set_dblink_conn(common::sqlclient::ObISQLConnection *dblink_conn) { int ret = OB_SUCCESS; - if (OB_ISNULL(session_info_)) { +#ifdef OB_BUILD_DBLINK + uint32_t sessid = 0; + oceanbase::common::sqlclient::ObTenantDblinkKeeper *tenant_dblink_keeper = MTL(oceanbase::common::sqlclient::ObTenantDblinkKeeper*); + if (OB_ISNULL(session_info_) || OB_ISNULL(tenant_dblink_keeper)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexcepted null ptr", K(ret)); + LOG_WARN("unexcepted null ptr", K(ret), KP(session_info_), KP(tenant_dblink_keeper)); + } else if (FALSE_IT(sessid = session_info_->get_sessid())) { } else if (OB_ISNULL(dblink_conn)) { //do nothing - } else if (OB_FAIL(add_var_to_array_no_dup(dblink_conn_holder_array_, reinterpret_cast(dblink_conn)))) { - LOG_WARN("session faild to hold a dblink connection", KP(dblink_conn), K(session_info_->get_sessid()), K(ret)); - } else { - LOG_TRACE("session succ to hold a dblink connection", KP(dblink_conn), K(session_info_->get_sessid()), K(ret), K(lbt())); + } else if (OB_FAIL(tenant_dblink_keeper->set_dblink_conn(sessid, dblink_conn))) { + LOG_WARN("failed to set dblink", KP(dblink_conn), K(sessid), KP(tenant_dblink_keeper), K(ret)); } + LOG_TRACE("set_dblink_conn", K(ret), KP(dblink_conn), K(sessid), K(lbt())); +#endif return ret; } int ObDblinkCtxInSession::clean_dblink_conn(const bool force_disconnect) { int ret = OB_SUCCESS; +#ifdef OB_BUILD_DBLINK + uint32_t sessid = 0; common::sqlclient::ObISQLConnection *dblink_conn =NULL; - if (OB_ISNULL(session_info_)) { + oceanbase::common::sqlclient::ObTenantDblinkKeeper *tenant_dblink_keeper = MTL(oceanbase::common::sqlclient::ObTenantDblinkKeeper*); + if (OB_ISNULL(tenant_dblink_keeper)) { + // do nothing + } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexcepted null ptr", K(ret)); + LOG_WARN("unexcepted null ptr", K(ret), KP(session_info_), KP(tenant_dblink_keeper)); + } else if (FALSE_IT(sessid = session_info_->get_sessid())) { + } else if (OB_FAIL(tenant_dblink_keeper->clean_dblink_conn(sessid, force_disconnect))) { + LOG_WARN("failed to set dblink", KP(dblink_conn), K(sessid), KP(tenant_dblink_keeper), K(force_disconnect), K(ret)); } - for (int64_t i = 0; OB_SUCC(ret) && i < dblink_conn_holder_array_.count(); ++i) { - dblink_conn = reinterpret_cast(dblink_conn_holder_array_.at(i)); - if (OB_UNLIKELY(NULL == dblink_conn)) { - // do nothing - } else { - dblink_conn->set_reverse_link_creadentials(false); - common::sqlclient::ObCommonServerConnectionPool * server_conn_pool = NULL; - server_conn_pool = dblink_conn->get_common_server_pool(); - if (NULL == server_conn_pool) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("server_conn_pool of dblink connection is NULL", K(this), K(dblink_conn), K(i), K(ret)); - } else { - const bool need_disconnect = force_disconnect || !dblink_conn->usable(); - if (OB_FAIL(server_conn_pool->release(dblink_conn, !need_disconnect))) { - LOG_WARN("session failed to release dblink connection", K(session_info_->get_sessid()), K(this), KP(dblink_conn), K(i), K(ret)); - } else { - LOG_TRACE("session succ to release dblink connection", K(session_info_->get_sessid()), K(this), KP(dblink_conn), K(i), K(ret)); - } - } - } - } - dblink_conn_holder_array_.reset(); + tx_id_.reset(); arena_alloc_.reset(); reverse_dblink_ = NULL; reverse_dblink_buf_ = NULL; sys_var_reverse_info_buf_ = NULL; sys_var_reverse_info_buf_size_ = 0; +#endif return ret; } diff --git a/src/sql/dblink/ob_dblink_utils.h b/src/sql/dblink/ob_dblink_utils.h index 9fbf09e15e..f607526dd8 100644 --- a/src/sql/dblink/ob_dblink_utils.h +++ b/src/sql/dblink/ob_dblink_utils.h @@ -34,10 +34,18 @@ class ObDblinkService { public: #ifdef OB_BUILD_DBLINK - static uint64_t get_current_tenant_id(); static common::sqlclient::ObTenantOciEnvs * get_tenant_oci_envs(); static int init_oci_envs_func_ptr(); #endif + static int get_charset_id(ObSQLSessionInfo *session_info, + uint16_t &charset_id, + uint16_t &ncharset_id); + static int init_dblink_param_ctx(common::sqlclient::dblink_param_ctx ¶m_ctx, + sql::ObSQLSessionInfo *session_info, + ObIAllocator &allocator, + uint64_t dblink_id, + common::sqlclient::DblinkDriverProto link_type = common::sqlclient::DblinkDriverProto::DBLINK_DRV_OB, + common::sqlclient::DblinkPoolType pool_type = common::sqlclient::DblinkPoolType::DBLINK_POOL_DEF); static int check_lob_in_result(common::sqlclient::ObMySQLResult *result, bool &have_lob); static int get_length_from_type_text(ObString &type_text, int32_t &length); static int get_local_session_vars(sql::ObSQLSessionInfo *session_info, @@ -50,6 +58,25 @@ public: const char *&set_client_charset, const char *&set_connection_charset, const char *&set_results_charset); + static int get_set_transaction_isolation_cstr(sql::ObSQLSessionInfo *session_info, + const char *&set_isolation_level); +public: + static const char *SET_ISOLATION_LEVEL_READ_COMMITTED; + static const char *SET_ISOLATION_LEVEL_REPEATABLE_READ; + static const char *SET_ISOLATION_LEVEL_SERIALIZABLE; + static const char *SET_ISOLATION_LEVEL_READ_COMMITTED_MYSQL_MODE; + static const char *SET_ISOLATION_LEVEL_REPEATABLE_READ_MYSQL_MODE; + static const char *SET_ISOLATION_LEVEL_SERIALIZABLE_MYSQL_MODE; + static const char *SET_RESULTS_CHARSET_NULL; + static const char *SET_CLIENT_CHARSET_UTF8MB4; + static const char *SET_CLIENT_CHARSET_GBK; + static const char *SET_CLIENT_CHARSET_BINARY; + static const char *SET_CONNECTION_CHARSET_UTF8MB4; + static const char *SET_CONNECTION_CHARSET_GBK; + static const char *SET_CONNECTION_CHARSET_BINARY; + static const char *SET_RESULTS_CHARSET_UTF8MB4; + static const char *SET_RESULTS_CHARSET_GBK; + static const char *SET_RESULTS_CHARSET_BINARY; }; enum DblinkGetConnType { @@ -120,7 +147,8 @@ private: class ObDblinkUtils { public: - static int has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink = false); + static int has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool enable_check_any_dblink = false); + static int gather_dblink_id(const ObDMLStmt *stmt, ObIArray &dblink_id_array); }; class ObSQLSessionInfo; @@ -134,7 +162,8 @@ public: reverse_dblink_(NULL), reverse_dblink_buf_(NULL), sys_var_reverse_info_buf_(NULL), - sys_var_reverse_info_buf_size_(0) + sys_var_reverse_info_buf_size_(0), + tx_id_() {} ~ObDblinkCtxInSession() { @@ -151,11 +180,13 @@ public: } int register_dblink_conn_pool(common::sqlclient::ObCommonServerConnectionPool *dblink_conn_pool); int free_dblink_conn_pool(); - int get_dblink_conn(uint64_t dblink_id, common::sqlclient::ObISQLConnection *&dblink_conn); + int get_dblink_conn(uint64_t dblink_id, common::sqlclient::ObISQLConnection *&dblink_conn, uint32_t tm_sessid = 0); + static int revert_dblink_conn(common::sqlclient::ObISQLConnection *&dblink_conn); int set_dblink_conn(common::sqlclient::ObISQLConnection *dblink_conn); int clean_dblink_conn(const bool force_disconnect); inline bool is_dblink_xa_tras() { return !dblink_conn_holder_array_.empty(); } int get_reverse_link(ObReverseLink *&reverse_dblink); + transaction::ObTransID &get_tx_id() { return tx_id_; } private: ObSQLSessionInfo *session_info_; ObReverseLink *reverse_dblink_; @@ -166,6 +197,7 @@ private: ObArray dblink_conn_pool_array_; //for dblink read to free connection when session drop. ObArray dblink_conn_holder_array_; //for dblink write to hold connection during transaction. ObString last_reverse_info_values_; + transaction::ObTransID tx_id_; }; struct ObParamPosIdx diff --git a/src/sql/engine/dml/ob_link_dml_op.cpp b/src/sql/engine/dml/ob_link_dml_op.cpp index 11bb340723..7330ec923e 100644 --- a/src/sql/engine/dml/ob_link_dml_op.cpp +++ b/src/sql/engine/dml/ob_link_dml_op.cpp @@ -114,13 +114,11 @@ int ObLinkDmlOp::send_reverse_link_info(transaction::ObTransID &tx_id) int ObLinkDmlOp::inner_execute_link_stmt(const char *link_stmt) { int ret = OB_SUCCESS; - transaction::ObTransID tx_id; - if (OB_ISNULL(dblink_proxy_) || OB_ISNULL(dblink_conn_) || OB_ISNULL(link_stmt)) { + ObSQLSessionInfo *session = ctx_.get_my_session(); + if (OB_ISNULL(dblink_proxy_) || OB_ISNULL(dblink_conn_) || OB_ISNULL(link_stmt) || OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("dblink_proxy or link_stmt is NULL", K(ret), KP(dblink_proxy_), KP(link_stmt), KP(dblink_conn_)); - } else if (OB_FAIL(ObTMService::tm_rm_start(ctx_, link_type_, dblink_conn_, tx_id))) { - LOG_WARN("failed to tm_rm_start", K(ret), K(dblink_id_), K(dblink_conn_)); - } else if (MY_SPEC.is_reverse_link_ && OB_FAIL(send_reverse_link_info(tx_id))) { + LOG_WARN("dblink_proxy or link_stmt is NULL", K(ret), KP(dblink_proxy_), KP(link_stmt), KP(dblink_conn_), KP(session)); + } else if (MY_SPEC.is_reverse_link_ && OB_FAIL(send_reverse_link_info(session->get_dblink_context().get_tx_id()))) { LOG_WARN("failed to send reverse link info", K(ret), K(link_stmt)); } else if (OB_FAIL(dblink_proxy_->dblink_write(dblink_conn_, affected_rows_, link_stmt))) { LOG_WARN("write failed", K(ret), K(link_stmt)); @@ -133,7 +131,8 @@ int ObLinkDmlOp::inner_execute_link_stmt(const char *link_stmt) void ObLinkDmlOp::reset_dblink() { int tmp_ret = OB_SUCCESS; - // when it is oci connection, does need terminate stmt like read, because write will terminate stmt after execute_update immediately + // when it is oci connection, does not need terminate stmt like read, because write will terminate stmt after execute_update immediately + ObDblinkCtxInSession::revert_dblink_conn(dblink_conn_); // release rlock locked by get_dblink_conn tenant_id_ = OB_INVALID_ID; dblink_id_ = OB_INVALID_ID; dblink_proxy_ = NULL; @@ -146,19 +145,22 @@ int ObLinkDmlOp::inner_open() ObSQLSessionInfo *session = ctx_.get_my_session(); ObPhysicalPlanCtx *plan_ctx = ctx_.get_physical_plan_ctx(); stmt_buf_len_ += head_comment_length_; - if (OB_ISNULL(session) || OB_ISNULL(plan_ctx)) { + in_xa_transaction_ = true; // link dml aways in xa trasaction + dblink_id_ = MY_SPEC.dblink_id_; + dblink_proxy_ = GCTX.dblink_proxy_; + if (OB_ISNULL(session) || OB_ISNULL(plan_ctx) || OB_ISNULL(dblink_proxy_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("session or plan_ctx is NULL", K(ret), KP(session), KP(plan_ctx)); + LOG_WARN("session or plan_ctx or dblink_proxy_ is NULL", K(ret), KP(session), KP(plan_ctx), KP(dblink_proxy_)); } else if (FALSE_IT(tenant_id_ = session->get_effective_tenant_id())) { + } else if (FALSE_IT(sessid_ = session->get_sessid())) { } else if (OB_FAIL(set_next_sql_req_level())) { LOG_WARN("failed to set next sql req level", K(ret)); - } else if (OB_FAIL(init_dblink(MY_SPEC.dblink_id_, GCTX.dblink_proxy_, true))) { - LOG_WARN("failed to init dblink", K(ret), K(MY_SPEC.dblink_id_)); + } else if (OB_FAIL(init_dblink())) { + LOG_WARN("failed to init dblink", K(ret), K(dblink_id_)); } else if (OB_ISNULL(stmt_buf_ = static_cast(allocator_.alloc(stmt_buf_len_)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to init stmt buf", K(ret), K(stmt_buf_len_)); } else { - LOG_DEBUG("succ to open link dml", K(lbt())); } return ret; diff --git a/src/sql/engine/dml/ob_link_op.cpp b/src/sql/engine/dml/ob_link_op.cpp index b5a1431636..16c30d0aca 100644 --- a/src/sql/engine/dml/ob_link_op.cpp +++ b/src/sql/engine/dml/ob_link_op.cpp @@ -108,79 +108,67 @@ ObLinkOp::ObLinkOp(ObExecContext &exec_ctx, const ObOpSpec &spec, ObOpInput *inp stmt_buf_len_(STMT_BUF_BLOCK), next_sql_req_level_(0), link_type_(DBLINK_DRV_OB), - in_xa_trascaction_(false) + in_xa_transaction_(false), + tm_sessid_(0) {} -int ObLinkOp::init_dblink(uint64_t dblink_id, ObDbLinkProxy *dblink_proxy, bool in_xa_trascaction) +int ObLinkOp::init_dblink() { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; - dblink_param_ctx param_ctx; ObSQLSessionInfo * my_session = NULL; common::sqlclient::ObISQLConnection *dblink_conn = NULL; my_session = ctx_.get_my_session(); ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_); - in_xa_trascaction_ = in_xa_trascaction; - dblink_id_ = dblink_id; - if (OB_NOT_NULL(dblink_proxy_)) { - ret = OB_INIT_TWICE; - LOG_WARN("link scan ctx already inited", K(ret)); - } else if (OB_ISNULL(dblink_proxy)) { + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_ISNULL(dblink_proxy_)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("dblink_proxy is NULL", K(ret)); + LOG_WARN("dblink_proxy_ is NULL", K(ret)); } else if (OB_ISNULL(my_session) || OB_ISNULL(plan_ctx)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("my_session or plan_ctx is NULL", K(my_session), K(plan_ctx), K(ret)); - } else if (FALSE_IT(sessid_ = my_session->get_sessid())) { + LOG_WARN("my_session or plan_ctx is NULL", KP(my_session), KP(plan_ctx), K(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) { LOG_WARN("failed to get schema guard", K(ret), K(tenant_id_)); - } else if (OB_FAIL(schema_guard.get_dblink_schema(tenant_id_, dblink_id, dblink_schema_))) { - LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id_), K(dblink_id)); + } else if (OB_FAIL(schema_guard.get_dblink_schema(tenant_id_, dblink_id_, dblink_schema_))) { + LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id_), K(dblink_id_)); } else if (OB_ISNULL(dblink_schema_)) { ret = OB_DBLINK_NOT_EXIST_TO_ACCESS; - LOG_WARN("dblink schema is NULL", K(ret), K(dblink_id)); - } else if (FALSE_IT(set_link_driver_proto(static_cast(dblink_schema_->get_driver_proto())))) { - // do nothing - } else if (OB_FAIL(ObLinkOp::init_dblink_param_ctx(ctx_, - param_ctx, - link_type_, - tenant_id_, - dblink_id_, - sessid_, - next_sql_req_level_))) { - LOG_WARN("failed to init dblink param ctx", K(ret)); - } else if (OB_FAIL(dblink_proxy->create_dblink_pool(param_ctx, - dblink_schema_->get_host_addr(), - dblink_schema_->get_tenant_name(), - dblink_schema_->get_user_name(), - dblink_schema_->get_plain_password(), - dblink_schema_->get_database_name(), - dblink_schema_->get_conn_string(), - dblink_schema_->get_cluster_name()))) { - LOG_WARN("failed to create dblink pool", K(ret)); - } else if (OB_FAIL(my_session->get_dblink_context().get_dblink_conn(dblink_id, dblink_conn))) { + LOG_WARN("dblink schema is NULL", K(ret), K(dblink_id_)); + } else if (FALSE_IT(link_type_ = static_cast(dblink_schema_->get_driver_proto()))) { + } else if (OB_FAIL(my_session->get_dblink_context().get_dblink_conn(dblink_id_, dblink_conn, tm_sessid_))) { LOG_WARN("failed to get dblink connection from session", K(my_session), K(sessid_), K(ret)); } else { - if (NULL == dblink_conn) { - if (OB_FAIL(ObDblinkService::get_local_session_vars(my_session, allocator_, param_ctx))) { - LOG_WARN("failed to get local session vars", K(ret)); - } else if (OB_FAIL(dblink_proxy->acquire_dblink(param_ctx, dblink_conn_))) { - LOG_WARN("failed to acquire dblink", K(ret), K(param_ctx)); + if (NULL == dblink_conn) { // nothing about transaction + if (OB_FAIL(ObDblinkService::init_dblink_param_ctx(dblink_param_ctx_, + my_session, + allocator_, // useless in oracle mode + dblink_id_, + link_type_))) { + LOG_WARN("failed to init dblink param ctx", K(ret), K(dblink_param_ctx_), K(dblink_id_), K(link_type_)); + } else if (OB_FAIL(dblink_proxy_->create_dblink_pool(dblink_param_ctx_, + dblink_schema_->get_host_addr(), + dblink_schema_->get_tenant_name(), + dblink_schema_->get_user_name(), + dblink_schema_->get_plain_password(), + dblink_schema_->get_database_name(), + dblink_schema_->get_conn_string(), + dblink_schema_->get_cluster_name()))) { + LOG_WARN("failed to create dblink pool", K(ret)); + } else if (OB_FAIL(dblink_proxy_->acquire_dblink(dblink_param_ctx_, dblink_conn_))) { + LOG_WARN("failed to acquire dblink", K(ret), K(dblink_param_ctx_)); } else if (OB_FAIL(my_session->get_dblink_context().register_dblink_conn_pool(dblink_conn_->get_common_server_pool()))) { LOG_WARN("failed to register dblink conn pool to current session", K(ret)); - } else if (in_xa_trascaction_ && lib::is_oracle_mode() && - OB_FAIL(my_session->get_dblink_context().set_dblink_conn(dblink_conn_))) { - LOG_WARN("failed to set dblink connection to session", K(in_xa_trascaction_), K(my_session), K(sessid_), K(ret)); } else { - LOG_TRACE("link op get connection from dblink pool", K(in_xa_trascaction_), KP(dblink_conn_), K(lbt())); + LOG_TRACE("link op get connection from dblink pool", K(in_xa_transaction_), KP(dblink_conn_), K(lbt())); } - } else { + } else if (dblink_conn->get_dblink_driver_proto() != link_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("wrong driver proto", K(ret), K(dblink_conn->get_dblink_driver_proto()), K(link_type_), K(next_sql_req_level_)); + } else { // about transaction dblink_conn_ = dblink_conn; - in_xa_trascaction_ = true; //to tell link scan op don't release dblink_conn_ - LOG_TRACE("link op get connection from xa transaction", K(dblink_id), KP(dblink_conn_)); - } - if (OB_SUCC(ret)) { - dblink_proxy_ = dblink_proxy; + in_xa_transaction_ = true; //to tell link scan op don't release dblink_conn_ + LOG_TRACE("link op get connection from xa transaction", K(dblink_id_), KP(dblink_conn_)); } } return ret; @@ -385,59 +373,6 @@ int ObLinkSpec::set_param_infos(const ObIArray ¶m_infos) return ret; } -int ObLinkOp::init_dblink_param_ctx(ObExecContext &exec_ctx, - common::sqlclient::dblink_param_ctx ¶m_ctx, - common::sqlclient::DblinkDriverProto link_type, - uint64_t tenant_id, - uint64_t dblink_id, - uint32_t session_id, - int64_t next_sql_req_level) -{ - int ret = OB_SUCCESS; - uint16_t charset_id = 0; - uint16_t ncharset_id = 0; - if (OB_FAIL(get_charset_id(exec_ctx, charset_id, ncharset_id))) { - LOG_WARN("failed to get session charset id", K(ret)); - } else { - param_ctx.charset_id_ = charset_id; - param_ctx.ncharset_id_ = ncharset_id; - param_ctx.pool_type_ = DblinkPoolType::DBLINK_POOL_DEF; - param_ctx.tenant_id_ = tenant_id; - param_ctx.dblink_id_ = dblink_id; - param_ctx.link_type_ = link_type; - param_ctx.sessid_ = session_id; - param_ctx.sql_request_level_ = next_sql_req_level; - } - return ret; -} - -int ObLinkOp::get_charset_id(ObExecContext &exec_ctx, - uint16_t &charset_id, - uint16_t &ncharset_id) -{ - int ret = OB_SUCCESS; - ObSQLSessionInfo *sess_info = NULL; - if (OB_ISNULL(sess_info = exec_ctx.get_my_session())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("null session info", K(ret)); - } else { - ObCollationType coll_type = sess_info->get_nls_collation(); - ObCollationType ncoll_type = sess_info->get_nls_collation_nation(); - ObCharsetType cs_type = ObCharset::charset_type_by_coll(coll_type); - ObCharsetType ncs_type = ObCharset::charset_type_by_coll(ncoll_type); - if (CHARSET_INVALID == cs_type || CHARSET_INVALID == ncs_type) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to get charset id", K(ret), K(coll_type)); - } else { - charset_id = static_cast(ObCharset::charset_type_to_ora_charset_id(cs_type)); - ncharset_id = static_cast(ObCharset::charset_type_to_ora_charset_id(ncs_type)); - LOG_DEBUG("get charset id", K(ret), K(charset_id), K(ncharset_id), - K(cs_type), K(ncs_type), K(coll_type), K(ncoll_type)); - } - } - return ret; -} - void ObLinkOp::reset_link_sql() { if (OB_NOT_NULL(stmt_buf_)) { diff --git a/src/sql/engine/dml/ob_link_op.h b/src/sql/engine/dml/ob_link_op.h index 77025abaf1..fea9339508 100644 --- a/src/sql/engine/dml/ob_link_op.h +++ b/src/sql/engine/dml/ob_link_op.h @@ -51,23 +51,13 @@ public: explicit ObLinkOp(ObExecContext &exec_ctx, const ObOpSpec &spec, ObOpInput *input); virtual ~ObLinkOp() { destroy(); } virtual void destroy() { reset(); } - - inline void set_link_driver_proto(common::sqlclient::DblinkDriverProto type) { link_type_ = type; } virtual void reset() = 0; - int init_dblink(uint64_t dblink_id, common::ObDbLinkProxy *dblink_proxy, bool in_xa_trascaction = false); + int init_dblink(); int execute_link_stmt(const common::ObString &link_stmt_fmt, const common::ObIArray ¶m_infos, const ObParamStore ¶m_store, ObReverseLink *reverse_link = NULL); virtual int inner_execute_link_stmt(const char *link_stmt) = 0; - static int init_dblink_param_ctx(ObExecContext &exec_ctx, - common::sqlclient::dblink_param_ctx ¶m_ctx, - common::sqlclient::DblinkDriverProto link_type, - uint64_t tenant_id, - uint64_t dblink_id, - uint32_t session_id, - int64_t next_sql_req_level); - static int get_charset_id(ObExecContext &exec_ctx, uint16_t &charset_id, uint16_t &ncharset_id); protected: int combine_link_stmt(const common::ObString &link_stmt_fmt, const common::ObIArray ¶m_infos, @@ -90,7 +80,9 @@ protected: int64_t next_sql_req_level_; static const int64_t STMT_BUF_BLOCK; common::sqlclient::DblinkDriverProto link_type_; - bool in_xa_trascaction_; // is dblink write/read remote database in xa transaction + bool in_xa_transaction_; // is dblink write/read remote database in xa transaction + common::sqlclient::dblink_param_ctx dblink_param_ctx_; + uint32_t tm_sessid_; // only used by link scan static const char * head_comment_fmt_; static const int64_t head_comment_length_; static const char *proxy_route_info_fmt_; diff --git a/src/sql/engine/ob_physical_plan.cpp b/src/sql/engine/ob_physical_plan.cpp index e5f789474e..a996092c97 100644 --- a/src/sql/engine/ob_physical_plan.cpp +++ b/src/sql/engine/ob_physical_plan.cpp @@ -97,8 +97,6 @@ ObPhysicalPlan::ObPhysicalPlan(MemoryContext &mem_context /* = CURRENT_CONTEXT * stat_(), op_stats_(), need_drive_dml_query_(false), - tx_id_(-1), - tm_sessid_(-1), var_init_exprs_(allocator_), is_returning_(false), is_late_materialized_(false), @@ -228,9 +226,6 @@ void ObPhysicalPlan::reset() append_table_id_ = 0; stat_.expected_worker_map_.destroy(); stat_.minimal_worker_map_.destroy(); - tx_id_ = -1; - tm_sessid_ = -1; - var_init_exprs_.reset(); need_record_plan_info_ = false; logical_plan_.reset(); is_enable_px_fast_reclaim_ = false; @@ -239,7 +234,6 @@ void ObPhysicalPlan::reset() udf_has_dml_stmt_ = false; mview_ids_.reset(); } - void ObPhysicalPlan::destroy() { #ifndef NDEBUG diff --git a/src/sql/engine/ob_physical_plan.h b/src/sql/engine/ob_physical_plan.h index f79586c7c5..a9808263e3 100644 --- a/src/sql/engine/ob_physical_plan.h +++ b/src/sql/engine/ob_physical_plan.h @@ -453,7 +453,7 @@ public: inline const ObExprFrameInfo &get_expr_frame_info() const { return expr_frame_info_; } const ObOpSpec *get_root_op_spec() const { return root_op_spec_; } - inline bool is_link_dml_plan() { + inline bool is_link_dml_plan() const { bool is_link_dml = false; if (NULL != get_root_op_spec()) { is_link_dml = oceanbase::sql::ObPhyOperatorType::PHY_LINK_DML == get_root_op_spec()->type_; @@ -619,8 +619,6 @@ public: //@todo: yuchen.wyc add a temporary member to mark whether //the DML statement needs to be executed through get_next_row bool need_drive_dml_query_; - int64_t tx_id_; //for dblink recover xa tx - int64_t tm_sessid_; //for dblink get connection attached on tm session ExprFixedArray var_init_exprs_; private: bool is_returning_; //是否设置了returning diff --git a/src/sql/engine/ob_physical_plan_ctx.cpp b/src/sql/engine/ob_physical_plan_ctx.cpp index 2e8392c712..e3a6d8f779 100644 --- a/src/sql/engine/ob_physical_plan_ctx.cpp +++ b/src/sql/engine/ob_physical_plan_ctx.cpp @@ -116,7 +116,11 @@ ObPhysicalPlanCtx::ObPhysicalPlanCtx(common::ObIAllocator &allocator) enable_rich_format_(false), all_local_session_vars_(allocator), mview_ids_(allocator), - last_refresh_scns_(allocator) + last_refresh_scns_(allocator), + tx_id_(0), + tm_sessid_(0), + hint_xa_trans_stop_check_lock_(false), + main_xa_trans_branch_(false) { } diff --git a/src/sql/engine/ob_physical_plan_ctx.h b/src/sql/engine/ob_physical_plan_ctx.h index 645eb30840..eeda4dd287 100644 --- a/src/sql/engine/ob_physical_plan_ctx.h +++ b/src/sql/engine/ob_physical_plan_ctx.h @@ -465,6 +465,16 @@ public: ObIArray &get_array_param_groups() { return array_param_groups_; } int set_all_local_session_vars(ObIArray &all_local_session_vars); int get_local_session_vars(int64_t idx, const ObLocalSessionVar *&local_vars); + void set_tx_id(int64_t tx_id) { tx_id_ = tx_id; } + int64_t get_tx_id() const { return tx_id_; } + void set_tm_sessid(int64_t tm_sessid) { tm_sessid_ = tm_sessid; } + int64_t get_tm_sessid() const { return tm_sessid_; } + void set_hint_xa_trans_stop_check_lock(int64_t hint_xa_trans_stop_check_lock) { hint_xa_trans_stop_check_lock_ = hint_xa_trans_stop_check_lock; } + int64_t get_hint_xa_trans_stop_check_lock() const { return hint_xa_trans_stop_check_lock_; } + void set_main_xa_trans_branch(int64_t main_xa_trans_branch) { main_xa_trans_branch_ = main_xa_trans_branch; } + int64_t get_main_xa_trans_branch() const { return main_xa_trans_branch_; } + ObIArray &get_dblink_ids() { return dblink_ids_; } + inline int keep_dblink_id(uint64_t dblink_id) { return add_var_to_array_no_dup(dblink_ids_, dblink_id); } private: int init_param_store_after_deserialize(); void reset_datum_frame(char *frame, int64_t expr_cnt); @@ -610,6 +620,11 @@ private: // for last_refresh_scn expr to get last_refresh_scn for rt mview used in query common::ObFixedArray mview_ids_; common::ObFixedArray last_refresh_scns_; + int64_t tx_id_; //for dblink recover xa tx + uint32_t tm_sessid_; //for dblink get connection attached on tm session + bool hint_xa_trans_stop_check_lock_; // for dblink to stop check stmt lock in xa trans + bool main_xa_trans_branch_; // for dblink to indicate weather this sql is executed in main_xa_trans_branch + ObSEArray dblink_ids_; }; } diff --git a/src/sql/engine/sequence/ob_sequence_op.cpp b/src/sql/engine/sequence/ob_sequence_op.cpp index 0c601e190c..91d97a38be 100644 --- a/src/sql/engine/sequence/ob_sequence_op.cpp +++ b/src/sql/engine/sequence/ob_sequence_op.cpp @@ -230,13 +230,11 @@ int ObRemoteSequenceExecutor::init_dblink_connection(ObExecContext &ctx) LOG_WARN("dblink schema is NULL", K(ret), K(dblink_id_)); } else if (FALSE_IT(link_type_ = static_cast(dblink_schema->get_driver_proto()))) { // do nothing - } else if (OB_FAIL(ObLinkOp::init_dblink_param_ctx(ctx, - param_ctx, - link_type_, - tenant_id, + } else if (OB_FAIL(ObDblinkService::init_dblink_param_ctx(param_ctx, + my_session, + ctx.get_allocator(), // uselees in oracle mode dblink_id_, - sessid_, - my_session->get_next_sql_request_level()))) { + link_type_))) { LOG_WARN("failed to init dblink param ctx", K(ret)); } else if (OB_FAIL(dblink_proxy->create_dblink_pool(param_ctx, dblink_schema->get_host_addr(), @@ -258,6 +256,8 @@ int ObRemoteSequenceExecutor::init_dblink_connection(ObExecContext &ctx) LOG_WARN("failed to register dblink conn pool to current session", K(ret)); } else if (OB_FAIL(my_session->get_dblink_context().set_dblink_conn(dblink_conn_))) { LOG_WARN("failed to set dblink connection to session", K(my_session), K(sessid_), K(ret)); + } else if (OB_FAIL(my_session->get_dblink_context().get_dblink_conn(param_ctx.dblink_id_, dblink_conn_))) { // will add a rlock on dblink conn, means this dblink_conn_ is inuse + LOG_WARN("failed to get dblink connection from session", K(ret), K(param_ctx.dblink_id_)); } else { LOG_TRACE("link op get connection from dblink pool", KP(dblink_conn_), K(lbt())); } @@ -316,6 +316,10 @@ void ObRemoteSequenceExecutor::destroy() LOG_WARN("failed to close oci result", K(ret)); } #endif + // release rlock on dblink_conn + if (OB_SUCCESS != (ret = ObDblinkCtxInSession::revert_dblink_conn(dblink_conn_))) { + LOG_WARN("failed to revert dblink conn", K(ret), KP(dblink_conn_)); + } //release dblink connection by session sessid_ = 0; dblink_conn_ = NULL; diff --git a/src/sql/engine/table/ob_link_scan_op.cpp b/src/sql/engine/table/ob_link_scan_op.cpp index bedf24548c..993348d2d5 100644 --- a/src/sql/engine/table/ob_link_scan_op.cpp +++ b/src/sql/engine/table/ob_link_scan_op.cpp @@ -50,7 +50,6 @@ ObLinkScanOp::ObLinkScanOp(ObExecContext &exec_ctx, const ObOpSpec &spec, ObOpIn iter_end_(false), row_allocator_(), iterated_rows_(-1), - tm_session_(NULL), tm_rm_connection_(NULL), reverse_link_(NULL), conn_type_(sql::DblinkGetConnType::DBLINK_POOL), @@ -62,6 +61,7 @@ void ObLinkScanOp::reset() { tz_info_ = NULL; dblink_schema_ = NULL; + tm_sessid_ = 0; reset_result(); reset_link_sql(); reset_dblink(); @@ -152,7 +152,6 @@ int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) uint16_t ncharset_id = 0; ObSQLSessionInfo * my_session = NULL; my_session = ctx_.get_my_session(); - transaction::ObTransID tx_id; bool have_lob = false; res_.set_enable_use_result(true); bool new_snapshot = false; @@ -174,8 +173,6 @@ int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) } else if (OB_ISNULL(dblink_proxy_) || OB_ISNULL(my_session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected NULL", K(ret), KP(dblink_proxy_), KP(my_session)); - } else if (need_tx(my_session) && OB_FAIL(ObTMService::tm_rm_start(ctx_, link_type_, dblink_conn_, tx_id))) { - LOG_WARN("failed to tm_rm_start", K(ret), K(dblink_id_), K(dblink_conn_), K(sessid_)); #ifdef OB_BUILD_DBLINK } else if (OB_FAIL(init_conn_snapshot(new_snapshot))) { LOG_WARN("init conn snapshot failed", K(ret)); @@ -207,7 +204,7 @@ int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) ret = OB_NOT_SUPPORTED; LOG_WARN("dblink not support lob type", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "dblink fetch lob type data"); - } else if (OB_FAIL(ObLinkOp::get_charset_id(ctx_, charset_id, ncharset_id))) { + } else if (OB_FAIL(ObDblinkService::get_charset_id(my_session, charset_id, ncharset_id))) { LOG_WARN("failed to get charset id", K(ret)); } else if (OB_FAIL(result_->set_expected_charset_id(charset_id, ncharset_id))) {// for oci dblink set expected result charset, actually useless... LOG_WARN("failed to set result set expected charset", K(ret), K(charset_id), K(ncharset_id)); @@ -245,13 +242,20 @@ void ObLinkScanOp::reset_dblink() LOG_WARN_RET(tmp_ret, "free dblink snapshot failed"); } #endif - if (OB_NOT_NULL(dblink_proxy_) && OB_NOT_NULL(dblink_conn_) && !in_xa_trascaction_ && + if (OB_NOT_NULL(dblink_proxy_) && OB_NOT_NULL(dblink_conn_) && !in_xa_transaction_ && OB_SUCCESS != (tmp_ret = dblink_proxy_->release_dblink(link_type_, dblink_conn_))) { LOG_WARN_RET(tmp_ret, "failed to release connection", K(tmp_ret)); } if (OB_NOT_NULL(reverse_link_)) { reverse_link_->close(); } + if (in_xa_transaction_ && OB_NOT_NULL(dblink_conn_)) { + ObDblinkCtxInSession::revert_dblink_conn(dblink_conn_); // release rlock locked by get_dblink_conn + } + if (OB_NOT_NULL(tm_rm_connection_)) { + ObDblinkCtxInSession::revert_dblink_conn(tm_rm_connection_); // release rlock locked by get_dblink_conn + } + tenant_id_ = OB_INVALID_ID; dblink_id_ = OB_INVALID_ID; dblink_proxy_ = NULL; @@ -282,21 +286,22 @@ int ObLinkScanOp::inner_open() ObSQLSessionInfo *session = ctx_.get_my_session(); ObPhysicalPlanCtx *plan_ctx = ctx_.get_physical_plan_ctx(); const ObPhysicalPlan *phy_plan = MY_SPEC.get_phy_plan(); - int64_t tm_sessid = -1; reverse_link_ = NULL; stmt_buf_len_ += head_comment_length_; - if (NULL != phy_plan) { - tm_sessid = phy_plan->tm_sessid_; - } - if (OB_ISNULL(session) || OB_ISNULL(plan_ctx)) { + dblink_id_ = MY_SPEC.dblink_id_; + dblink_proxy_ = GCTX.dblink_proxy_; + if (OB_ISNULL(session) || OB_ISNULL(plan_ctx) || OB_ISNULL(phy_plan) || OB_ISNULL(dblink_proxy_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("session or plan_ctx is NULL", K(ret), KP(session), KP(plan_ctx)); + LOG_WARN("session or plan_ctx or dblink_proxy_ or dblink_proxy_ is NULL", K(ret), KP(session), KP(plan_ctx), KP(phy_plan), KP(dblink_proxy_)); + } else if (FALSE_IT(tenant_id_ = session->get_effective_tenant_id())) { + } else if (FALSE_IT(sessid_ = session->get_sessid())) { + } else if (FALSE_IT(tm_sessid_ = plan_ctx->get_tm_sessid())) { } else if (OB_FAIL(set_next_sql_req_level())) { LOG_WARN("failed to set next sql req level", K(ret)); } else if (FALSE_IT(tenant_id_ = session->get_effective_tenant_id())) { } else if (MY_SPEC.is_reverse_link_) { // RM process sql within @! and @xxxx! send by TM - LOG_DEBUG("link scan op, RM process sql within @! and @xxxx! send by TM"); + LOG_TRACE("link scan op, RM process sql within @! and @xxxx! send by TM"); conn_type_ = sql::DblinkGetConnType::TEMP_CONN; ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_); if (OB_ISNULL(plan_ctx)) { @@ -310,46 +315,38 @@ int ObLinkScanOp::inner_open() } else if (OB_FAIL(reverse_link_->open(next_sql_req_level_))) { LOG_WARN("failed to open reverse_link", K(ret)); } - } else if (-1 != tm_sessid) { // TM process sql within @xxxx send by RM - LOG_DEBUG("link scan op, TM process sql within @xxxx send by RM", K(tm_sessid)); - sql::ObSQLSessionMgr *session_mgr = GCTX.session_mgr_; - if (OB_ISNULL(session_mgr)) { + } else if (0 != tm_sessid_) { // TM process sql within @xxxx send by RM + LOG_TRACE("link scan op, TM process sql within @xxxx send by RM", K(tm_sessid_)); + if (OB_FAIL(session->get_dblink_context().get_dblink_conn(MY_SPEC.dblink_id_, tm_rm_connection_, tm_sessid_))) { + LOG_TRACE("link scan op failed to get tm_tm_connection", K(tm_sessid_), K(MY_SPEC.dblink_id_), K(ret)); + } else if (OB_ISNULL(tm_rm_connection_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), KP(session_mgr)); - } else if (OB_FAIL(session_mgr->get_session(static_cast(tm_sessid), tm_session_))) { - LOG_WARN("failed to get session", K(ret), K(tm_sessid)); + LOG_WARN("unexcepted null ptr", K(tm_sessid_), K(MY_SPEC.dblink_id_), K(ret)); } else { - if (NULL != tm_session_ && - tm_session_->get_dblink_context().get_dblink_conn(MY_SPEC.dblink_id_, tm_rm_connection_)) { - LOG_WARN("failed to get dblink connection from session", KP(tm_session_), K(ret)); - } else if (NULL != tm_rm_connection_){ - conn_type_ = sql::DblinkGetConnType::TM_CONN; - LOG_DEBUG("get tm sesseion and connection", KP(tm_session_), KP(tm_rm_connection_)); - } - session_mgr->revert_session(tm_session_); - tm_session_ = NULL; + conn_type_ = sql::DblinkGetConnType::TM_CONN; + link_type_ = tm_rm_connection_->get_dblink_driver_proto(); + LOG_TRACE("get tm sesseion and connection", KP(tm_rm_connection_), K(link_type_), K(tm_sessid_), K(sessid_), K(ret)); } + } else if (OB_FAIL(init_dblink())) { + LOG_WARN("failed to init dblink", K(ret), K(dblink_id_), K(MY_SPEC.is_reverse_link_)); } - if (OB_FAIL(ret)) { - // do nothing - } else if (sql::DblinkGetConnType::DBLINK_POOL == conn_type_ && - OB_FAIL(init_dblink(MY_SPEC.dblink_id_, GCTX.dblink_proxy_, MY_SPEC.has_for_update_))) { - LOG_WARN("failed to init dblink", K(ret), K(MY_SPEC.dblink_id_), K(MY_SPEC.is_reverse_link_)); - } else if (OB_FAIL(init_tz_info(TZ_INFO(session)))) { + if (OB_SUCC(ret)) { + if (OB_FAIL(init_tz_info(TZ_INFO(session)))) { LOG_WARN("failed to tz info", K(ret), KP(session)); - } else { - row_allocator_.set_tenant_id(tenant_id_); - row_allocator_.set_label("linkoprow"); - row_allocator_.set_ctx_id(ObCtxIds::WORK_AREA); - } - if (OB_SUCC(ret) && OB_ISNULL(stmt_buf_ = static_cast(allocator_.alloc(stmt_buf_len_)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to init stmt buf", K(ret), K(stmt_buf_len_)); + } else if (OB_ISNULL(stmt_buf_ = static_cast(allocator_.alloc(stmt_buf_len_)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to init stmt buf", K(ret), K(stmt_buf_len_)); + } else { + row_allocator_.set_tenant_id(tenant_id_); + row_allocator_.set_label("linkoprow"); + row_allocator_.set_ctx_id(ObCtxIds::WORK_AREA); + } + LOG_TRACE("succ to open link scan op", K(dblink_id_), K(tm_sessid_), K(MY_SPEC.is_reverse_link_), K(conn_type_), K(ret)); } // close reverse_link if (NULL != reverse_link_ && OB_FAIL(ret)) { reverse_link_->close(); - LOG_DEBUG("close reverse link", KP(reverse_link_), K(ret)); + LOG_TRACE("close reverse link", KP(reverse_link_), K(ret)); } return ret; } @@ -544,19 +541,5 @@ int ObLinkScanOp::inner_get_next_batch(const int64_t max_row_cnt) return ret; } -// PLEASE check the input parameter in public interface -bool ObLinkScanOp::need_tx(const ObSQLSessionInfo *my_session) const -{ - bool ret_bool = false; - if (MY_SPEC.has_for_update_) { - // case 1, if select for update, tm_rm_start is required to be called. - ret_bool = true; - } else if (false && my_session->is_in_transaction()) { - // case 2, if select in transaction, tm_rm_start is required to be called. - ret_bool = true; - } - return ret_bool; -} - } // end namespace sql } // end namespace oceanbase diff --git a/src/sql/engine/table/ob_link_scan_op.h b/src/sql/engine/table/ob_link_scan_op.h index 7d9a7a4444..a2ede9e2c5 100644 --- a/src/sql/engine/table/ob_link_scan_op.h +++ b/src/sql/engine/table/ob_link_scan_op.h @@ -64,7 +64,6 @@ private: bool iter_end_; common::ObArenaAllocator row_allocator_; int64_t iterated_rows_; - ObSQLSessionInfo *tm_session_; common::sqlclient::ObISQLConnection *tm_rm_connection_; ObReverseLink *reverse_link_; sql::DblinkGetConnType conn_type_; diff --git a/src/sql/ob_result_set.cpp b/src/sql/ob_result_set.cpp index d0fda92eab..5b08b84a8a 100644 --- a/src/sql/ob_result_set.cpp +++ b/src/sql/ob_result_set.cpp @@ -49,6 +49,8 @@ #include "observer/ob_req_time_service.h" #include "sql/dblink/ob_dblink_utils.h" #include "sql/dblink/ob_tm_service.h" +#include "storage/tx/ob_xa_ctx.h" +#include "sql/engine/dml/ob_link_op.h" #include using namespace oceanbase::sql; @@ -301,14 +303,17 @@ int ObResultSet::start_stmt() int ret = OB_SUCCESS; bool ac = true; ObPhysicalPlan* phy_plan = static_cast(cache_obj_guard_.get_cache_obj()); - if (OB_ISNULL(phy_plan)) { + ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(get_exec_context()); + if (OB_ISNULL(phy_plan) || OB_ISNULL(plan_ctx)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid inner state", K(phy_plan)); + LOG_WARN("invalid inner state", KP(phy_plan), KP(plan_ctx)); } else if (OB_ISNULL(phy_plan->get_root_op_spec())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("root_op_spec of phy_plan is NULL", K(phy_plan), K(ret)); } else if (OB_FAIL(my_session_.get_autocommit(ac))) { LOG_WARN("fail to get autocommit", K(ret)); + } else if (lib::is_oracle_mode() && OB_FAIL(ObSqlTransControl::dblink_xa_prepare(get_exec_context()))) { + LOG_WARN("failed to prepare dblink xa connection", K(ret)); } else if (phy_plan->is_link_dml_plan() || phy_plan->has_link_sfd()) { if (ac) { my_session_.set_autocommit(false); @@ -316,8 +321,8 @@ int ObResultSet::start_stmt() } LOG_DEBUG("dblink xa trascaction need skip start_stmt()", K(PHY_LINK_DML == phy_plan->get_root_op_spec()->type_), K(my_session_.get_dblink_context().is_dblink_xa_tras())); } else { - if (-1 != phy_plan->tx_id_) { - const transaction::ObTransID tx_id(phy_plan->tx_id_); + if (0 < plan_ctx->get_tx_id()) { + const transaction::ObTransID tx_id(plan_ctx->get_tx_id()); if (OB_FAIL(sql::ObTMService::recover_tx_for_callback(tx_id, get_exec_context()))) { LOG_WARN("failed to recover dblink xa transaction", K(ret), K(tx_id)); } else { @@ -325,7 +330,7 @@ int ObResultSet::start_stmt() LOG_DEBUG("succ to recover dblink xa transaction", K(tx_id)); } } else { - LOG_DEBUG("recover dblink xa skip", K(phy_plan->tx_id_)); + LOG_DEBUG("recover dblink xa skip", K(plan_ctx->get_tx_id())); } bool in_trans = my_session_.get_in_transaction(); @@ -355,6 +360,28 @@ int ObResultSet::start_stmt() } get_trans_state().set_start_stmt_executed(OB_SUCC(ret)); } + if (OB_SUCC(ret) && + (plan_ctx->get_hint_xa_trans_stop_check_lock() || + plan_ctx->get_main_xa_trans_branch())) { + transaction::ObTxDesc *tx_desc = my_session_.get_tx_desc(); + ObXACtx *xa_ctx = NULL; + const transaction::ObXATransID xid = my_session_.get_xid(); + LOG_TRACE("stop check stmt lock", KP(plan_ctx), K(ret), K(plan_ctx->get_hint_xa_trans_stop_check_lock()), K(plan_ctx->get_main_xa_trans_branch()), K(tx_desc)); + if (OB_ISNULL(tx_desc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), KP(tx_desc), KP(xa_ctx)); + } else if (OB_ISNULL(xa_ctx = tx_desc->get_xa_ctx())) { + LOG_TRACE("not in xa transaction, skip", K(ret), KP(tx_desc), KP(xa_ctx)); + } else if (xa_ctx->is_executing()) { + if (OB_FAIL(xa_ctx->stop_check_stmt_lock(xid))) { + LOG_WARN("failed to stop check stmt lock", K(ret), K(xid)); + } else { + // is_executing() can not tell us weather xa checking lock is stoped, need a var to record this. + //succ to stop check stmt lock", K(ret), K(xid)); + xa_checking_lock_stoped_ = true; + } + } + } } NG_TRACE(sql_start_stmt_end); return ret; @@ -364,7 +391,30 @@ int ObResultSet::end_stmt(const bool is_rollback) { int ret = OB_SUCCESS; NG_TRACE(start_end_stmt); - if (get_trans_state().is_start_stmt_executed() + ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(get_exec_context()); + if (OB_ISNULL(plan_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid inner state", K(plan_ctx)); + } else if (xa_checking_lock_stoped_ && + (plan_ctx->get_hint_xa_trans_stop_check_lock() || + plan_ctx->get_main_xa_trans_branch())) { + transaction::ObTxDesc *tx_desc = my_session_.get_tx_desc(); + LOG_TRACE("start check stmt lock", KP(plan_ctx), K(ret), K(plan_ctx->get_hint_xa_trans_stop_check_lock()), K(plan_ctx->get_main_xa_trans_branch()), K(tx_desc)); + ObXACtx *xa_ctx = NULL; + const transaction::ObXATransID xid = my_session_.get_xid(); + if (OB_ISNULL(tx_desc) || OB_ISNULL(xa_ctx = tx_desc->get_xa_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), KP(tx_desc), KP(xa_ctx)); + } else if (OB_FAIL(xa_ctx->start_check_stmt_lock(xid))) { + LOG_WARN("failed to start check stmt lock", K(ret), K(xid)); + } else { + LOG_TRACE("succ to start check stmt lock", K(ret), K(xid)); + } + xa_checking_lock_stoped_ = false; + } + if (OB_FAIL(ret)) { + // do nothing + } else if (get_trans_state().is_start_stmt_executed() && get_trans_state().is_start_stmt_success()) { ObPhysicalPlan* physical_plan_ = static_cast(cache_obj_guard_.get_cache_obj()); if (OB_ISNULL(physical_plan_)) { diff --git a/src/sql/ob_result_set.h b/src/sql/ob_result_set.h index 861801d3bd..03cb9a3496 100644 --- a/src/sql/ob_result_set.h +++ b/src/sql/ob_result_set.h @@ -435,6 +435,7 @@ private: bool is_com_filed_list_; //used to mark COM_FIELD_LIST bool need_revert_tx_; //dblink bool will_retry_; // the query will retry, to figure out the final close + bool xa_checking_lock_stoped_; common::ObString wild_str_;//uesd to save filed wildcard in COM_FIELD_LIST; common::ObString ps_sql_; // for sql in pl bool is_init_; @@ -512,6 +513,7 @@ inline ObResultSet::ObResultSet(ObSQLSessionInfo &session, common::ObIAllocator is_com_filed_list_(false), need_revert_tx_(false), will_retry_(false), + xa_checking_lock_stoped_(false), wild_str_(), ps_sql_(), is_init_(false), diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index 4fc3cb6bb6..d41778a4c2 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -8810,6 +8810,13 @@ int ObSPIService::spi_execute_dblink(ObExecContext &exec_ctx, session->get_timezone_info()), call_stmt); OZ (spi_after_execute_dblink(session, routine_info, allocator, params, exec_params)); } + if (OB_NOT_NULL(dblink_conn)) { + int tmp_ret = OB_SUCCESS; + if (OB_FAIL(ObDblinkCtxInSession::revert_dblink_conn(dblink_conn))) { + ret = (ret == OB_SUCCESS) ? tmp_ret : ret; + LOG_WARN("failed to revert dblink conn", K(ret), K(tmp_ret), KP(dblink_conn)); + } + } return ret; } diff --git a/src/sql/ob_sql_trans_control.cpp b/src/sql/ob_sql_trans_control.cpp index f5ce75cc30..8ed9c8ab57 100644 --- a/src/sql/ob_sql_trans_control.cpp +++ b/src/sql/ob_sql_trans_control.cpp @@ -533,7 +533,6 @@ int ObSqlTransControl::start_stmt(ObExecContext &exec_ctx) ObDASCtx &das_ctx = DAS_CTX(exec_ctx); transaction::ObTransService *txs = NULL; uint64_t tenant_id = 0; - CK (OB_NOT_NULL(session), OB_NOT_NULL(plan_ctx), OB_NOT_NULL(plan)); OX (tenant_id = session->get_effective_tenant_id()); OX (session->get_trans_result().reset()); @@ -640,6 +639,89 @@ bool print_log = false; return ret; } +int ObSqlTransControl::dblink_xa_prepare(ObExecContext &exec_ctx) +{ + int ret = OB_SUCCESS; + uint16_t charset_id = 0; + uint16_t ncharset_id = 0; + uint64_t tenant_id = -1; + uint32_t sessid = -1; + uint32_t tm_sessid = 0; + common::ObDbLinkProxy *dblink_proxy = GCTX.dblink_proxy_; + sql::ObSQLSessionMgr *session_mgr = GCTX.session_mgr_; + ObSQLSessionInfo *session = GET_MY_SESSION(exec_ctx); + ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(exec_ctx); + const ObPhysicalPlan *phy_plan = plan_ctx->get_phy_plan(); + common::ObArenaAllocator allocator; + ObSchemaGetterGuard schema_guard; + if (OB_ISNULL(session) || OB_ISNULL(dblink_proxy) || OB_ISNULL(phy_plan) || OB_ISNULL(session_mgr) || OB_ISNULL(plan_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), KP(session), KP(dblink_proxy), KP(phy_plan), KP(session_mgr), KP(plan_ctx)); + } else if (lib::is_oracle_mode() && + !plan_ctx->get_dblink_ids().empty() && + plan_ctx->get_main_xa_trans_branch()) { + if (OB_FAIL(ObDblinkService::get_charset_id(session, charset_id, ncharset_id))) { + LOG_WARN("failed to get session charset id", K(ret)); + } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), schema_guard))) { + LOG_WARN("failed to get schema guard", K(ret), K(session->get_effective_tenant_id())); + } else { + ObIArray &dblink_ids = plan_ctx->get_dblink_ids(); + tenant_id = session->get_effective_tenant_id(); + sessid = session->get_sessid(); + for(int64_t i = 0; OB_SUCC(ret) && i < dblink_ids.count(); ++i) { + uint64_t dblink_id = dblink_ids.at(i); + const ObDbLinkSchema *dblink_schema = NULL; + common::sqlclient::ObISQLConnection *dblink_conn = NULL; + if (OB_FAIL(schema_guard.get_dblink_schema(tenant_id, dblink_id, dblink_schema))) { + LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id), K(dblink_id)); + } else if (OB_ISNULL(dblink_schema)) { + ret = OB_DBLINK_NOT_EXIST_TO_ACCESS; + LOG_WARN("dblink schema is NULL", K(ret), K(dblink_id)); + } else if (OB_FAIL(session->get_dblink_context().get_dblink_conn(dblink_id, dblink_conn))) { + LOG_WARN("failed to get dblink connection from session", K(dblink_id), K(sessid), K(ret)); + } else if (OB_NOT_NULL(dblink_conn)) { + ObDblinkCtxInSession::revert_dblink_conn(dblink_conn); // release rlock locked by get_dblink_conn + } else { + common::sqlclient::dblink_param_ctx dblink_param_ctx; + if (OB_FAIL(ObDblinkService::init_dblink_param_ctx(dblink_param_ctx, + session, + allocator, //useless in oracle mode + dblink_id, + static_cast(dblink_schema->get_driver_proto())))) { + LOG_WARN("failed to init dblink param ctx", K(ret), K(dblink_param_ctx), K(dblink_id)); + } else if (OB_FAIL(dblink_proxy->create_dblink_pool(dblink_param_ctx, + dblink_schema->get_host_addr(), + dblink_schema->get_tenant_name(), + dblink_schema->get_user_name(), + dblink_schema->get_plain_password(), + dblink_schema->get_database_name(), + dblink_schema->get_conn_string(), + dblink_schema->get_cluster_name()))) { + LOG_WARN("failed to create dblink pool", K(ret)); + } else if (OB_FAIL(dblink_proxy->acquire_dblink(dblink_param_ctx, dblink_conn))) { + LOG_WARN("failed to acquire dblink", K(ret), K(dblink_param_ctx)); + } else if (OB_FAIL(session->get_dblink_context().register_dblink_conn_pool(dblink_conn->get_common_server_pool()))) { + LOG_WARN("failed to register dblink conn pool to current session", K(ret)); + } else if (OB_FAIL(session->get_dblink_context().set_dblink_conn(dblink_conn))) { + LOG_WARN("failed to set dblink connection to session", K(session), K(sessid), K(ret)); + } else if (OB_FAIL(ObTMService::tm_rm_start(exec_ctx, + static_cast(dblink_schema->get_driver_proto()), + dblink_conn, + session->get_dblink_context().get_tx_id()))) { + LOG_WARN("failed to tm_rm_start", K(ret), K(dblink_id), K(dblink_conn), K(sessid), K(static_cast(dblink_schema->get_driver_proto()))); + } else { + LOG_TRACE("link succ to prepare xa connection", KP(plan_ctx), K(ret), K(dblink_id), K(session->get_dblink_context().get_tx_id())); + } + } + } + } + } + if (OB_NOT_NULL(plan_ctx)) { + plan_ctx->get_dblink_ids().reset(); + } + return ret; +} + int ObSqlTransControl::stmt_sanity_check_(ObSQLSessionInfo *session, const ObPhysicalPlan *plan, ObPhysicalPlanCtx *plan_ctx) diff --git a/src/sql/ob_sql_trans_control.h b/src/sql/ob_sql_trans_control.h index d1d3afc26d..da7275aa12 100644 --- a/src/sql/ob_sql_trans_control.h +++ b/src/sql/ob_sql_trans_control.h @@ -193,6 +193,7 @@ public: const int64_t expire_ts, ObEndTransAsyncCallback *callback); static int start_stmt(ObExecContext &ctx); + static int dblink_xa_prepare(ObExecContext &exec_ctx); static int stmt_sanity_check_(ObSQLSessionInfo *session, const ObPhysicalPlan *plan, ObPhysicalPlanCtx *plan_ctx); diff --git a/src/sql/ob_sql_utils.cpp b/src/sql/ob_sql_utils.cpp index f34a39a2b4..5be2af7715 100644 --- a/src/sql/ob_sql_utils.cpp +++ b/src/sql/ob_sql_utils.cpp @@ -2149,10 +2149,11 @@ char ObSQLUtils::find_first_empty_char(const ObString &sql) int ObSQLUtils::reconstruct_sql(ObIAllocator &allocator, const ObStmt *stmt, ObString &sql, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params, - const ParamStore *param_store) + const ParamStore *param_store, + const ObSQLSessionInfo *session) { int ret = OB_SUCCESS; - ObSqlPrinter sql_printer(stmt, schema_guard, print_params, param_store); + ObSqlPrinter sql_printer(stmt, schema_guard, print_params, param_store, session); if (OB_ISNULL(stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(stmt), K(ret)); @@ -2228,7 +2229,8 @@ int ObSqlPrinter::inner_print(char *buf, int64_t buf_len, int64_t &res_len) stmt_, schema_guard_, print_params_, - param_store_); + param_store_, + session_); } int ObSQLUtils::print_sql(char *buf, @@ -2237,7 +2239,8 @@ int ObSQLUtils::print_sql(char *buf, const ObStmt *stmt, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params, - const ParamStore *param_store) + const ParamStore *param_store, + const ObSQLSessionInfo *session) { int ret = OB_SUCCESS; int64_t pos = 0; @@ -2268,7 +2271,9 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + false, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); printer.enable_print_temp_table_as_cte(); @@ -2284,7 +2289,8 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); if (OB_FAIL(printer.do_print())) { @@ -2300,7 +2306,8 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); if (OB_FAIL(printer.do_print())) { @@ -2315,7 +2322,8 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); if (OB_FAIL(printer.do_print())) { @@ -2330,7 +2338,8 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); if (OB_FAIL(printer.do_print())) { @@ -2345,7 +2354,8 @@ int ObSQLUtils::print_sql(char *buf, static_cast(reconstruct_stmt), schema_guard, print_params, - param_store); + param_store, + session); printer.set_is_root(true); printer.set_is_first_stmt_for_hint(true); if (OB_FAIL(printer.do_print())) { diff --git a/src/sql/ob_sql_utils.h b/src/sql/ob_sql_utils.h index 22e6275037..1e263f4511 100644 --- a/src/sql/ob_sql_utils.h +++ b/src/sql/ob_sql_utils.h @@ -128,11 +128,13 @@ public: ObSqlPrinter(const ObStmt *stmt, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params, - const ParamStore *param_store) : + const ParamStore *param_store, + const ObSQLSessionInfo *session) : stmt_(stmt), schema_guard_(schema_guard), print_params_(print_params), - param_store_(param_store) + param_store_(param_store), + session_(session) {} virtual int inner_print(char *buf, int64_t buf_len, int64_t &res_len) override; @@ -141,6 +143,7 @@ protected: ObSchemaGetterGuard *schema_guard_; ObObjPrintParams print_params_; const ParamStore *param_store_; + const ObSQLSessionInfo *session_; }; class ObSQLUtils @@ -425,14 +428,16 @@ public: static int reconstruct_sql(ObIAllocator &allocator, const ObStmt *stmt, ObString &sql, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params = ObObjPrintParams(), - const ParamStore *param_store = NULL); + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL); static int print_sql(char *buf, int64_t buf_len, int64_t &pos, const ObStmt *stmt, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params, - const ParamStore *param_store = NULL); + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL); static int wrap_expr_ctx(const stmt::StmtType &stmt_type, ObExecContext &exec_ctx, diff --git a/src/sql/optimizer/ob_del_upd_log_plan.cpp b/src/sql/optimizer/ob_del_upd_log_plan.cpp index b31aadcbed..a20f29ac4b 100644 --- a/src/sql/optimizer/ob_del_upd_log_plan.cpp +++ b/src/sql/optimizer/ob_del_upd_log_plan.cpp @@ -197,18 +197,21 @@ int ObDelUpdLogPlan::generate_dblink_raw_plan() LOG_WARN("failed to allocate link dml as top", K(ret)); } else if (OB_FAIL(make_candidate_plans(top))) { LOG_WARN("failed to make candidate plans", K(ret)); - } else if (OB_FAIL(static_cast(top)->set_link_stmt())) { - LOG_WARN("failed to set link stmt", K(ret)); } else { set_plan_root(top); bool has_reverse_link = false; 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 if (OB_FAIL(ObDblinkUtils::gather_dblink_id(stmt, static_cast(top)->get_related_dblink_ids()))) { + LOG_WARN("failed to exec gather_dblink_id", K(ret)); } else { uint64_t dblink_id = stmt->get_dblink_id(); top->set_dblink_id(dblink_id); static_cast(top)->set_reverse_link(has_reverse_link); static_cast(top)->set_dml_type(stmt->get_stmt_type()); + if (OB_FAIL(static_cast(top)->set_link_stmt())) { + LOG_WARN("failed to set link stmt", K(ret)); + } } } return ret; diff --git a/src/sql/optimizer/ob_log_link.cpp b/src/sql/optimizer/ob_log_link.cpp index 6a491dd557..4f88d0d9dc 100644 --- a/src/sql/optimizer/ob_log_link.cpp +++ b/src/sql/optimizer/ob_log_link.cpp @@ -210,39 +210,22 @@ int ObLogLink::set_link_stmt(const ObDMLStmt* stmt) print_param.for_dblink_ = 1; // only link scan need print flashback query for dblink table ObOptimizerContext *opt_ctx = NULL; - ObQueryCtx *query_ctx = NULL; ObSQLSessionInfo *session = NULL; - int64_t session_query_timeout_us = 0; - int64_t hint_query_timeout_us = 0; if (OB_ISNULL(stmt) || OB_ISNULL(plan) || OB_ISNULL(opt_ctx = &get_plan()->get_optimizer_context()) || OB_ISNULL(session = opt_ctx->get_session_info()) || OB_ISNULL(print_param.exec_ctx_ = opt_ctx->get_exec_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", KP(opt_ctx), KP(stmt), KP(session), KP(plan), K(ret)); - } else if (NULL == (query_ctx = stmt->get_query_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (FALSE_IT(hint_query_timeout_us = query_ctx->get_query_hint_for_update().get_global_hint().query_timeout_)) { - } else if (OB_FAIL(session->get_query_timeout(session_query_timeout_us))) { - LOG_WARN("failed to get session query timeout", K(ret)); - } else if (-1 == hint_query_timeout_us && - FALSE_IT(query_ctx->get_query_hint_for_update().get_global_hint().merge_query_timeout_hint(session_query_timeout_us))) { - // do nothing - } else if (FALSE_IT(query_ctx->get_query_hint_for_update().get_global_hint().set_flashback_read_tx_uncommitted(true))) { } else if (OB_FAIL(mark_exec_params(const_cast(stmt)))) { LOG_WARN("failed to mark exec params", K(ret)); - } else if (OB_FAIL(ObSQLUtils::reconstruct_sql(plan->get_allocator(), stmt, sql, opt_ctx->get_schema_guard(), print_param))) { + } else if (OB_FAIL(ObSQLUtils::reconstruct_sql(plan->get_allocator(), stmt, sql, opt_ctx->get_schema_guard(), print_param, NULL, session))) { LOG_WARN("failed to reconstruct link sql", KP(stmt), KP(plan), K(get_dblink_id()), K(ret)); } else { stmt_fmt_buf_ = sql.ptr(); stmt_fmt_len_ = sql.length(); LOG_DEBUG("loglink succ to reconstruct link sql", K(sql)); } - if (-1 == hint_query_timeout_us) { // restore query_timeout_hint - query_ctx->get_query_hint_for_update().get_global_hint().reset_query_timeout_hint(); - } - query_ctx->get_query_hint_for_update().get_global_hint().set_flashback_read_tx_uncommitted(false); return ret; } diff --git a/src/sql/optimizer/ob_log_link_dml.h b/src/sql/optimizer/ob_log_link_dml.h index ad9a70d2e1..e605e24429 100644 --- a/src/sql/optimizer/ob_log_link_dml.h +++ b/src/sql/optimizer/ob_log_link_dml.h @@ -30,10 +30,12 @@ public: virtual int get_explain_name_internal(char *buf, const int64_t buf_len, int64_t &pos) override; virtual int get_plan_item_info(PlanText &plan_text, ObSqlPlanItem &plan_item) override; inline void set_dml_type(stmt::StmtType type) { dml_type_ = type; } + inline ObIArray &get_related_dblink_ids() { return related_dblink_ids_; } private: virtual bool print_flashback_query() const override { return false; }; private: stmt::StmtType dml_type_; + common::ObSEArray related_dblink_ids_; // all dblinks related in this link dml sql }; } // namespace sql diff --git a/src/sql/optimizer/ob_select_log_plan.cpp b/src/sql/optimizer/ob_select_log_plan.cpp index f41d40cef8..dd110be73f 100644 --- a/src/sql/optimizer/ob_select_log_plan.cpp +++ b/src/sql/optimizer/ob_select_log_plan.cpp @@ -4255,46 +4255,18 @@ int ObSelectLogPlan::generate_normal_raw_plan() int ObSelectLogPlan::generate_dblink_raw_plan() { int ret = OB_SUCCESS; - ObQueryCtx *query_ctx = NULL; // dblink_info hint int64_t tx_id = -1; - int64_t tm_sessid = -1; + uint32_t tm_sessid = 0; + bool xa_trans_stop_check_lock = false; uint64_t dblink_id = OB_INVALID_ID; const ObSelectStmt *stmt = get_stmt(); ObLogicalOperator *top = NULL; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null ptr", K(ret)); - } else if (NULL == (query_ctx = stmt->get_query_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (FALSE_IT(dblink_id = stmt->get_dblink_id())) { - } else if (0 == dblink_id) { //dblink id = 0 means @!/@xxxx! - ObSQLSessionInfo *session = get_optimizer_context().get_session_info(); - oceanbase::sql::ObReverseLink *reverse_dblink_info = NULL; - if (NULL == session) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), KP(session)); - } else if (OB_FAIL(session->get_dblink_context().get_reverse_link(reverse_dblink_info))) { - LOG_WARN("failed to get reverse link info from session", K(ret), K(session->get_sessid())); - } else if (NULL == reverse_dblink_info) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else { - // set dblink_info, to unparse a link sql with dblink_info hint - query_ctx->get_query_hint_for_update().get_global_hint().merge_dblink_info_hint( - reverse_dblink_info->get_tx_id(), - reverse_dblink_info->get_tm_sessid()); - LOG_DEBUG("set tx_id_ and tm_sessid to stmt", - K(reverse_dblink_info->get_tx_id()), - K(reverse_dblink_info->get_tm_sessid())); - } } else { - // save dblink_info hint - tx_id = query_ctx->get_query_hint_for_update().get_global_hint().get_dblink_tx_id_hint(); - tm_sessid = query_ctx->get_query_hint_for_update().get_global_hint().get_dblink_tm_sessid_hint(); - // reset dblink hint, to unparse a link sql without dblink_info hint - query_ctx->get_query_hint_for_update().get_global_hint().reset_dblink_info_hint(); + dblink_id = stmt->get_dblink_id(); } if (OB_FAIL(ret)) { //do nothing @@ -4319,13 +4291,6 @@ int ObSelectLogPlan::generate_dblink_raw_plan() } else { top->mark_is_plan_root(); top->get_plan()->set_plan_root(top); - if (0 == dblink_id) { - // reset dblink info, to avoid affecting the next execution flow - query_ctx->get_query_hint_for_update().get_global_hint().reset_dblink_info_hint(); - } else { - // restore dblink_info hint, ensure that the next execution process can get the correct dblink_info - query_ctx->get_query_hint_for_update().get_global_hint().merge_dblink_info_hint(tx_id, tm_sessid); - } LOG_TRACE("succeed to allocate loglinkscan", K(dblink_id)); } return ret; diff --git a/src/sql/printer/ob_delete_stmt_printer.h b/src/sql/printer/ob_delete_stmt_printer.h index 156e929894..d35bb5c8ab 100644 --- a/src/sql/printer/ob_delete_stmt_printer.h +++ b/src/sql/printer/ob_delete_stmt_printer.h @@ -28,8 +28,9 @@ public: ObDeleteStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObDeleteStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL) : - ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store) {} + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL) : + ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session) {} virtual ~ObDeleteStmtPrinter() {} void init(char *buf, int64_t buf_len, int64_t *pos, ObDeleteStmt *stmt); diff --git a/src/sql/printer/ob_dml_stmt_printer.cpp b/src/sql/printer/ob_dml_stmt_printer.cpp index a8f493c7b9..997f9d0586 100644 --- a/src/sql/printer/ob_dml_stmt_printer.cpp +++ b/src/sql/printer/ob_dml_stmt_printer.cpp @@ -28,7 +28,8 @@ namespace sql ObDMLStmtPrinter::ObDMLStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObDMLStmt *stmt, ObSchemaGetterGuard *schema_guard, ObObjPrintParams print_params, - const ParamStore *param_store) + const ParamStore *param_store, + const ObSQLSessionInfo *session) : buf_(buf), buf_len_(buf_len), pos_(pos), @@ -39,7 +40,8 @@ ObDMLStmtPrinter::ObDMLStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, con schema_guard_(schema_guard), print_params_(print_params), expr_printer_(buf, buf_len, pos, schema_guard_, print_params_, param_store), - param_store_(param_store) + param_store_(param_store), + session_(session) { } @@ -56,6 +58,95 @@ void ObDMLStmtPrinter::init(char *buf, int64_t buf_len, int64_t *pos, ObDMLStmt print_cte_ = false; } +int ObDMLStmtPrinter::prepare_dblink_hint(ObQueryHint &query_hint_dblink) +{ + int ret = OB_SUCCESS; + if (!print_params_.for_dblink_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected to print dblink hint", K(ret), K(print_params_.for_dblink_)); + } else if (is_first_stmt_for_hint_) { + const ObQueryHint &query_hint = stmt_->get_query_ctx()->get_query_hint(); + const ObGlobalHint &global_hint = query_hint.get_global_hint(); + ObGlobalHint &global_hint_dblink = query_hint_dblink.get_global_hint(); + global_hint_dblink.merge_query_timeout_hint(global_hint.query_timeout_); + global_hint_dblink.merge_read_consistency_hint(global_hint.read_consistency_, global_hint.frozen_version_); + global_hint_dblink.merge_log_level_hint(global_hint.log_level_); + global_hint_dblink.force_trace_log_ = global_hint.force_trace_log_; + global_hint_dblink.monitor_ = global_hint.monitor_; + int64_t session_query_timeout_us = 0; + if (OB_ISNULL(session_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), K(lbt())); + } else if (stmt_->is_select_stmt()) { + uint64_t dblink_id = OB_INVALID_ID; + dblink_id = stmt_->get_dblink_id(); + if (0 == dblink_id) { + // set dblink_info, to unparse a link sql with dblink_info hint + oceanbase::sql::ObReverseLink *reverse_dblink_info = NULL; + if (OB_FAIL(const_cast(session_)->get_dblink_context().get_reverse_link(reverse_dblink_info))) { + LOG_WARN("failed to get reverse link info from session", K(ret), K(session_->get_sessid())); + } else if (NULL == reverse_dblink_info) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else { + query_hint_dblink.get_global_hint().merge_tm_sessid_tx_id(reverse_dblink_info->get_tx_id(), + reverse_dblink_info->get_tm_sessid()); + LOG_TRACE("set tx_id_ and tm_sessid to stmt", K(reverse_dblink_info->get_tx_id()), + K(reverse_dblink_info->get_tm_sessid())); + } + } else { + // reset dblink hint, to unparse a link sql without dblink_info hint + query_hint_dblink.get_global_hint().reset_tm_sessid_tx_id_hint(); + } + if ((session_->is_in_transaction() && + transaction::ObTxIsolationLevel::RC == session_->get_tx_desc()->get_isolation_level()) || + !session_->is_in_transaction()) { + query_hint_dblink.get_global_hint().set_flashback_read_tx_uncommitted(true); + } + // link scan have not xa_trans_stop_check_lock hint + query_hint_dblink.get_global_hint().set_xa_trans_stop_check_lock(false); + } else { // T_INSERT T_DELETE T_UPDATE T_MERGE + bool has_reverse_link = false; + // link dml have not tm_sessid and tx_id hint + query_hint_dblink.get_global_hint().reset_tm_sessid_tx_id_hint(); + 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 { + /** + restore xa_trans_stop_check_lock info, to avoid affecting the next execution flow. + if xa_trans_stop_check_lock == true and this is RM(0==dblink_id), RM will stop check xa lock. + eg: + step 1. + TM get sql1 like "insert into t2@my_link1 select a.c1, b.c2 from t1 a, t2@my_link1 b where a.c1=b.c1;", + and my_link1 and my_link2 have the same conneciton info. + step 2. + TM will send sql2 to RM like below + insert into "LCQ1"."T2"("C1","C2") select "A"."C1" AS "C1","LCQ1"."B"."C2" AS "C2" from "LCQ1"."T1"@! "A","LCQ1"."T2" "B" where ("A"."C1" = "LCQ1"."B"."C1") + TM will attach DBLINK_XA_TRANS_STOP_CHECK_LOCK hint to sql2, telling RM to stop check xa lock. + step 3. + RM get sql2, stop checking xa lock, then send sql3 like below to TM + "select * from T2@my_link2" + step 4. + TM get sql3, and send sql4 like below to RM + "select * from T2" + RM received sql4 and the meantime of excuting of sql2 is still runing. + sql4 can excuted directory without wait ending of sql2, cause sql2 has stoped check xa lock. + */ + // When TM detects a reverse link in the SQL sent to RM, add a xa_trans_stop_check_lock hint tag to the SQL. + query_hint_dblink.get_global_hint().set_xa_trans_stop_check_lock(has_reverse_link); + } + } + if (OB_SUCC(ret) && -1 == query_hint_dblink.get_global_hint().query_timeout_) { + if (OB_FAIL(session_->get_query_timeout(session_query_timeout_us))) { + LOG_WARN("failed to get session query timeout", K(ret)); + } else { + query_hint_dblink.get_global_hint().merge_query_timeout_hint(session_query_timeout_us); + } + } + } + return ret; +} + int ObDMLStmtPrinter::print_hint() { int ret = OB_SUCCESS; @@ -68,6 +159,12 @@ int ObDMLStmtPrinter::print_hint() DATA_PRINTF("%s", hint_begin); if (OB_SUCC(ret)) { const ObQueryHint &query_hint = stmt_->get_query_ctx()->get_query_hint(); + ObQueryHint query_hint_dblink; + if (print_params_.for_dblink_ && + is_first_stmt_for_hint_ && + OB_FAIL(prepare_dblink_hint(query_hint_dblink))) { + LOG_WARN("failed to print dblink hint", K(ret)); + } PlanText plan_text; plan_text.buf_ = buf_; plan_text.buf_len_ = buf_len_; @@ -76,7 +173,11 @@ int ObDMLStmtPrinter::print_hint() plan_text.type_ = print_params_.for_dblink_ ? EXPLAIN_DBLINK_STMT : EXPLAIN_UNINITIALIZED; // just for print hint, ExplainType set as invalid type - if (OB_FAIL(query_hint.print_stmt_hint(plan_text, *stmt_, is_first_stmt_for_hint_))) { + if (OB_FAIL(ret)) { + // do nothing + } else if (print_params_.for_dblink_ && is_first_stmt_for_hint_ && OB_FAIL(query_hint_dblink.get_global_hint().print_global_hint(plan_text))) { + LOG_WARN("failed to print stmt hint", K(ret)); + } else if (!print_params_.for_dblink_ && OB_FAIL(query_hint.print_stmt_hint(plan_text, *stmt_, is_first_stmt_for_hint_))) { LOG_WARN("failed to print stmt hint", K(ret)); } else if (plan_text.pos_ == *pos_) { // no hint, roolback buffer! @@ -1787,7 +1888,8 @@ int ObDMLStmtPrinter::print_subquery(const ObSelectStmt *subselect_stmt, schema_guard_, print_params_, param_store_, - subquery_print_params & FORCE_COL_ALIAS); + subquery_print_params & FORCE_COL_ALIAS, + session_); if (subquery_print_params & PRINT_CTE) { printer.enable_print_temp_table_as_cte(); } diff --git a/src/sql/printer/ob_dml_stmt_printer.h b/src/sql/printer/ob_dml_stmt_printer.h index d83fa6b265..2eef1f0227 100644 --- a/src/sql/printer/ob_dml_stmt_printer.h +++ b/src/sql/printer/ob_dml_stmt_printer.h @@ -92,7 +92,8 @@ public: ObDMLStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObDMLStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL); + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL); virtual ~ObDMLStmtPrinter(); void enable_print_temp_table_as_cte() { print_cte_ = true; } void disable_print_temp_table_as_cte() { print_cte_ = false; } @@ -112,6 +113,7 @@ public: bool no_print_alias = false); int print_table_with_subquery(const TableItem *table_item); int print_base_table(const TableItem *table_item); + int prepare_dblink_hint(ObQueryHint &query_hint_dblink); int print_hint(); void set_is_root(bool is_root) { is_root_ = is_root; } void set_is_first_stmt_for_hint(bool is_first_stmt) { is_first_stmt_for_hint_ = is_first_stmt; } @@ -161,6 +163,7 @@ protected: ObObjPrintParams print_params_; ObRawExprPrinter expr_printer_; const ParamStore *param_store_; + const ObSQLSessionInfo *session_; }; } diff --git a/src/sql/printer/ob_insert_all_stmt_printer.h b/src/sql/printer/ob_insert_all_stmt_printer.h index 22591b3cc6..5140a47584 100644 --- a/src/sql/printer/ob_insert_all_stmt_printer.h +++ b/src/sql/printer/ob_insert_all_stmt_printer.h @@ -28,8 +28,9 @@ public: ObInsertAllStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObInsertAllStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL) : - ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store) {} + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL) : + ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session) {} virtual ~ObInsertAllStmtPrinter() {} void init(char *buf, int64_t buf_len, int64_t *pos, ObInsertAllStmt *stmt); diff --git a/src/sql/printer/ob_insert_stmt_printer.h b/src/sql/printer/ob_insert_stmt_printer.h index 5f203be643..dd73df3f18 100644 --- a/src/sql/printer/ob_insert_stmt_printer.h +++ b/src/sql/printer/ob_insert_stmt_printer.h @@ -28,8 +28,9 @@ public: ObInsertStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObInsertStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL) : - ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store) {} + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL) : + ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session) {} virtual ~ObInsertStmtPrinter() {} void init(char *buf, int64_t buf_len, int64_t *pos, ObInsertStmt *stmt); diff --git a/src/sql/printer/ob_merge_stmt_printer.h b/src/sql/printer/ob_merge_stmt_printer.h index 26af877bc0..60c4984d93 100644 --- a/src/sql/printer/ob_merge_stmt_printer.h +++ b/src/sql/printer/ob_merge_stmt_printer.h @@ -29,8 +29,9 @@ public: ObMergeStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObMergeStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL) : - ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store) {} + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL) : + ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session) {} virtual ~ObMergeStmtPrinter() {} void init(char *buf, int64_t buf_len, int64_t *pos, ObMergeStmt *stmt); diff --git a/src/sql/printer/ob_select_stmt_printer.cpp b/src/sql/printer/ob_select_stmt_printer.cpp index 1394e1fb74..b94845b91f 100644 --- a/src/sql/printer/ob_select_stmt_printer.cpp +++ b/src/sql/printer/ob_select_stmt_printer.cpp @@ -282,7 +282,8 @@ int ObSelectStmtPrinter::print_set_op_stmt() schema_guard_, print_params_, param_store_, - /*force_col_alias*/true); + /*force_col_alias*/true, + session_); stmt_printer.set_column_list(column_list_); stmt_printer.set_is_first_stmt_for_hint(is_first_stmt_for_hint_); ObString set_op_str = ObString::make_string( diff --git a/src/sql/printer/ob_select_stmt_printer.h b/src/sql/printer/ob_select_stmt_printer.h index 5abd205318..eaee0c2a76 100644 --- a/src/sql/printer/ob_select_stmt_printer.h +++ b/src/sql/printer/ob_select_stmt_printer.h @@ -44,8 +44,9 @@ public: ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, const ParamStore *param_store, - const bool force_col_alias = false) - : ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store), + const bool force_col_alias = false, + const ObSQLSessionInfo *session = NULL) + : ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session), column_list_(NULL), force_col_alias_(force_col_alias) {} virtual ~ObSelectStmtPrinter() {} diff --git a/src/sql/printer/ob_update_stmt_printer.h b/src/sql/printer/ob_update_stmt_printer.h index d6d5060417..2a70fe5ca8 100644 --- a/src/sql/printer/ob_update_stmt_printer.h +++ b/src/sql/printer/ob_update_stmt_printer.h @@ -28,8 +28,9 @@ public: ObUpdateStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObUpdateStmt *stmt, ObSchemaGetterGuard *schema_guard, common::ObObjPrintParams print_params, - const ParamStore *param_store = NULL) : - ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store) {} + const ParamStore *param_store = NULL, + const ObSQLSessionInfo *session = NULL) : + ObDMLStmtPrinter(buf, buf_len, pos, stmt, schema_guard, print_params, param_store, session) {} virtual ~ObUpdateStmtPrinter() {} void init(char *buf, int64_t buf_len, int64_t *pos, ObUpdateStmt *stmt); diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 7e9ba7d82a..29e27154fb 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -12958,6 +12958,57 @@ int ObDMLResolver::inner_resolve_hints(const ParseNode &node, return ret; } +int ObDMLResolver::resolve_dblink_hint(const ParseNode &hint_node, + ObGlobalHint &global_hint) +{ + int ret = OB_SUCCESS; + ParseNode *child0 = NULL; + ParseNode *child1 = NULL; + if (OB_UNLIKELY(2 != hint_node.num_child_) || + OB_ISNULL(child0 = hint_node.children_[0]) || + OB_ISNULL(child1 = hint_node.children_[1])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected hint node", K(ret), + K(hint_node.num_child_), K(child0), K(child1)); + } else if (T_DBLINK_INFO != hint_node.type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected hint node", K(ret),K(hint_node.type_)); + } else { + if (T_VARCHAR == child0->type_) { // from ocenabase 4.3.0, dblink_info hint use trans_param-like kv hint + ObString dblink_info_param_str; + dblink_info_param_str.assign_ptr(child0->str_value_, static_cast(child0->str_len_)); + if (T_VARCHAR == child1->type_) { + ObString dblink_info_param_value; + dblink_info_param_value.assign_ptr(child1->str_value_, static_cast(child1->str_len_)); + if (!dblink_info_param_str.case_compare("DBLINK_XA_TRANS_STOP_CHECK_LOCK")) { + if (!dblink_info_param_value.case_compare("TRUE")) { + global_hint.set_xa_trans_stop_check_lock(true); + } + } else { + // do nothing + } + } else if (T_INT == child1->type_) { + if (!dblink_info_param_str.case_compare("DBLINK_TM_SESSID")) { + global_hint.merge_dblink_info_tm_sessid(child1->value_); + } else if (!dblink_info_param_str.case_compare("DBLINK_TX_ID")) { + global_hint.merge_dblink_info_tx_id(child1->value_); + } else { + // do nothing + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected value type in opt param hint", "type", get_type_name(child1->type_)); + } + } else if (T_INT == child0->type_) { // compat oceanbase below 4.3.0 + global_hint.merge_tm_sessid_tx_id(child0->value_, child1->value_); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected value type in opt param hint", "type", get_type_name(child0->type_)); + } + } + return ret; +} + // resolve and deal conflict global hint, // if hint_node is not global hint, set is_global_hint to false. int ObDMLResolver::resolve_global_hint(const ParseNode &hint_node, @@ -12993,8 +13044,8 @@ int ObDMLResolver::resolve_global_hint(const ParseNode &hint_node, break; } case T_DBLINK_INFO: { - CHECK_HINT_PARAM(hint_node, 2) { - global_hint.merge_dblink_info_hint(child0->value_, child1->value_); + if (OB_FAIL(resolve_dblink_hint(hint_node, global_hint))) { + LOG_WARN("failed to resolve dblink hint", K(ret)); } break; } diff --git a/src/sql/resolver/dml/ob_dml_resolver.h b/src/sql/resolver/dml/ob_dml_resolver.h index eb7f08c258..6ce15dccdf 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.h +++ b/src/sql/resolver/dml/ob_dml_resolver.h @@ -862,6 +862,8 @@ private: int resolve_global_hint(const ParseNode &hint_node, ObGlobalHint &global_hint, bool &resolved_hint); + int resolve_dblink_hint(const ParseNode &hint_node, + ObGlobalHint &global_hint); int resolve_transform_hint(const ParseNode &hint_node, bool &resolved_hint, ObIArray &trans_hints); diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index 164e7925c9..b813a8c993 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -58,6 +58,26 @@ int ObPhyPlanHint::deep_copy(const ObPhyPlanHint &other, ObIAllocator &allocator return ret; } +int ObDBLinkHit::print(char *buf, int64_t &buf_len, int64_t &pos, const char* outline_indent) const { + int ret = OB_SUCCESS; + if (0 < tx_id_) { + if (OB_FAIL(BUF_PRINTF("%s%s(\'%s\' , %ld)", outline_indent, "DBLINK_INFO", "DBLINK_TX_ID", tx_id_))) { + LOG_WARN("failed to print hint", K(ret), K("DBLINK_INFO(%s , %ld)")); + } + } + if (OB_SUCC(ret) && 0 != tm_sessid_) { + if (OB_FAIL(BUF_PRINTF("%s%s(\'%s\' , %u)", outline_indent, "DBLINK_INFO", "DBLINK_TM_SESSID", tm_sessid_))) { + LOG_WARN("failed to print hint", K(ret), K("DBLINK_INFO(%s , %u)")); + } + } + if (OB_SUCC(ret) && hint_xa_trans_stop_check_lock_) { + if (OB_FAIL(BUF_PRINTF("%s%s(\'%s\' , \'%s\')", outline_indent, "DBLINK_INFO", "DBLINK_XA_TRANS_STOP_CHECK_LOCK", "TRUE"))) { + LOG_WARN("failed to print hint", K(ret), K("DBLINK_INFO(%s , %s)")); + } + } + return 0; +} + int ObGlobalHint::merge_alloc_op_hints(const ObIArray &alloc_op_hints) { int ret = OB_SUCCESS; @@ -131,19 +151,34 @@ void ObGlobalHint::merge_query_timeout_hint(int64_t hint_time) } } -void ObGlobalHint::merge_dblink_info_hint(int64_t tx_id, int64_t tm_sessid) +void ObGlobalHint::merge_tm_sessid_tx_id(int64_t tx_id, uint32_t tm_sessid) { - if (-1 != tx_id && -1 != tm_sessid) { - tx_id_ = tx_id; - tm_sessid_ = tm_sessid; - LOG_DEBUG("merge dblink info hint", K(tx_id_), K(tm_sessid_)); + if (0 < tx_id && 0 != tm_sessid) { + dblink_hints_.tx_id_ = tx_id; + dblink_hints_.tm_sessid_ = tm_sessid; + int ret = 0; } } -void ObGlobalHint::reset_dblink_info_hint() +void ObGlobalHint::merge_dblink_info_tx_id(int64_t tx_id) { - tx_id_ = -1; - tm_sessid_ = -1; + if (0 < tx_id) { + dblink_hints_.tx_id_ = tx_id; + } +} + +void ObGlobalHint::merge_dblink_info_tm_sessid(uint32_t tm_sessid) +{ + if (0 != tm_sessid) { + dblink_hints_.tm_sessid_ = tm_sessid; + } +} + +void ObGlobalHint::reset_tm_sessid_tx_id_hint() +{ + int ret = 0; + dblink_hints_.tx_id_ = 0; + dblink_hints_.tm_sessid_ = 0; } void ObGlobalHint::merge_max_concurrent_hint(int64_t max_concurrent) @@ -281,7 +316,7 @@ bool ObGlobalHint::has_hint_exclude_concurrent() const || -1 != topk_precision_ || 0 != sharding_minimum_row_count_ || UNSET_QUERY_TIMEOUT != query_timeout_ - || (-1 != tx_id_ && -1 != tm_sessid_) + || dblink_hints_.has_valid_hint() || common::INVALID_CONSISTENCY != read_consistency_ || OB_USE_PLAN_CACHE_INVALID != plan_cache_policy_ || false != force_trace_log_ @@ -305,8 +340,6 @@ void ObGlobalHint::reset() topk_precision_ = -1; sharding_minimum_row_count_ = 0; query_timeout_ = UNSET_QUERY_TIMEOUT; - tx_id_ = -1; - tm_sessid_ = -1; read_consistency_ = common::INVALID_CONSISTENCY; plan_cache_policy_ = OB_USE_PLAN_CACHE_INVALID; force_trace_log_ = false; @@ -330,6 +363,7 @@ void ObGlobalHint::reset() flashback_read_tx_uncommitted_ = false; dynamic_sampling_ = ObGlobalHint::UNSET_DYNAMIC_SAMPLING; alloc_op_hints_.reuse(); + dblink_hints_.reset(); } int ObGlobalHint::merge_global_hint(const ObGlobalHint &other) @@ -338,7 +372,6 @@ int ObGlobalHint::merge_global_hint(const ObGlobalHint &other) merge_read_consistency_hint(other.read_consistency_, other.frozen_version_); merge_topk_hint(other.topk_precision_, other.sharding_minimum_row_count_); merge_query_timeout_hint(other.query_timeout_); - merge_dblink_info_hint(other.tx_id_, other.tm_sessid_); enable_lock_early_release_ |= other.enable_lock_early_release_; merge_log_level_hint(other.log_level_); enable_lock_early_release_ |= other.enable_lock_early_release_; @@ -357,6 +390,7 @@ int ObGlobalHint::merge_global_hint(const ObGlobalHint &other) osg_hint_.flags_ |= other.osg_hint_.flags_; has_dbms_stats_hint_ |= other.has_dbms_stats_hint_; flashback_read_tx_uncommitted_ |= other.flashback_read_tx_uncommitted_; + dblink_hints_ = other.dblink_hints_; merge_dynamic_sampling_hint(other.dynamic_sampling_); if (OB_FAIL(merge_alloc_op_hints(other.alloc_op_hints_))) { LOG_WARN("failed to merge alloc op hints", K(ret)); @@ -438,10 +472,8 @@ int ObGlobalHint::print_global_hint(PlanText &plan_text) const if (OB_SUCC(ret) && UNSET_QUERY_TIMEOUT != query_timeout_) { //QUERY_TIMEOUT PRINT_GLOBAL_HINT_NUM("QUERY_TIMEOUT", query_timeout_); } - if (OB_SUCC(ret) && -1 != tx_id_ && -1 != tm_sessid_) { //DBLINK_INFO - if (OB_FAIL(BUF_PRINTF("%s%s(%ld , %ld)", outline_indent, "DBLINK_INFO", tx_id_, tm_sessid_))) { - LOG_WARN("failed to print hint", K(ret), K("DBLINK_INFO(%lld , %lld)")); - } + if (OB_SUCC(ret) && OB_FAIL(dblink_hints_.print(buf, buf_len, pos, outline_indent))) { // DBLINK_INFO + LOG_WARN("failed to print dblink hints", K(ret), K(dblink_hints_)); } if (OB_SUCC(ret) && plan_cache_policy_ != OB_USE_PLAN_CACHE_INVALID) { //USE_PLAN_CACHE const char *plan_cache_policy = "INVALID"; diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index e82c4f330a..9ce064209d 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -134,6 +134,24 @@ struct ObOptParamHint class ObDDLSchemaVersionHint; +struct ObDBLinkHit { + ObDBLinkHit() { reset(); } + void reset() { + tx_id_ = 0; + tm_sessid_ =0; + hint_xa_trans_stop_check_lock_ = false; + } + int print(char *buf, int64_t &buf_len, int64_t &pos, const char* outline_indent) const; + bool has_valid_hint() const { return (0 < tx_id_ && 0 != tm_sessid_) || hint_xa_trans_stop_check_lock_; } + + TO_STRING_KV(K_(tx_id), + K_(tm_sessid), + K_(hint_xa_trans_stop_check_lock)); + int64_t tx_id_; + uint32_t tm_sessid_; + bool hint_xa_trans_stop_check_lock_; +}; + struct ObGlobalHint { ObGlobalHint() { reset(); } void reset(); @@ -167,8 +185,10 @@ struct ObGlobalHint { int merge_alloc_op_hints(const ObIArray &alloc_op_hints); void merge_query_timeout_hint(int64_t hint_time); void reset_query_timeout_hint() { query_timeout_ = -1; } - void merge_dblink_info_hint(int64_t tx_id, int64_t tm_sessid); - void reset_dblink_info_hint(); + void merge_tm_sessid_tx_id(int64_t tx_id, uint32_t tm_sessid); + void merge_dblink_info_tx_id(int64_t tx_id); + void merge_dblink_info_tm_sessid(uint32_t tm_sessid); + void reset_tm_sessid_tx_id_hint(); void merge_max_concurrent_hint(int64_t max_concurrent); void merge_parallel_hint(int64_t parallel); void merge_parallel_dml_hint(ObPDMLOption pdml_option); @@ -187,8 +207,8 @@ struct ObGlobalHint { ObPDMLOption get_pdml_option() const { return pdml_option_; } ObParamOption get_param_option() const { return param_option_; } - int64_t get_dblink_tx_id_hint() const { return tx_id_; } - int64_t get_dblink_tm_sessid_hint() const { return tm_sessid_; } + int64_t get_dblink_tx_id_hint() const { return dblink_hints_.tx_id_; } + uint32_t get_dblink_tm_sessid_hint() const { return dblink_hints_.tm_sessid_; } int64_t get_parallel_degree() const { return parallel_ >= DEFAULT_PARALLEL ? parallel_ : UNSET_PARALLEL; } bool has_parallel_degree() const { return parallel_ >= DEFAULT_PARALLEL; } bool has_parallel_hint() const { return UNSET_PARALLEL != parallel_; } @@ -202,6 +222,8 @@ struct ObGlobalHint { inline void set_dbms_stats() { has_dbms_stats_hint_ = true; } bool get_flashback_read_tx_uncommitted() const { return flashback_read_tx_uncommitted_; } void set_flashback_read_tx_uncommitted(bool v) { flashback_read_tx_uncommitted_ = v; } + bool get_xa_trans_stop_check_lock() const { return dblink_hints_.hint_xa_trans_stop_check_lock_; } + void set_xa_trans_stop_check_lock(bool v) { dblink_hints_.hint_xa_trans_stop_check_lock_ = v; } bool has_append() const { return (osg_hint_.flags_ & ObOptimizerStatisticsGatheringHint::OB_APPEND_HINT) ? true : false; } @@ -237,8 +259,6 @@ struct ObGlobalHint { K_(topk_precision), K_(sharding_minimum_row_count), K_(query_timeout), - K_(tx_id), - K_(tm_sessid), K_(read_consistency), K_(plan_cache_policy), K_(force_trace_log), @@ -261,14 +281,13 @@ struct ObGlobalHint { K_(osg_hint), K_(has_dbms_stats_hint), K_(dynamic_sampling), - K_(alloc_op_hints)); + K_(alloc_op_hints), + K_(dblink_hints)); int64_t frozen_version_; int64_t topk_precision_; int64_t sharding_minimum_row_count_; int64_t query_timeout_; - int64_t tx_id_; - int64_t tm_sessid_; common::ObConsistencyLevel read_consistency_; ObPlanCachePolicy plan_cache_policy_; bool force_trace_log_; @@ -292,6 +311,7 @@ struct ObGlobalHint { bool flashback_read_tx_uncommitted_; int64_t dynamic_sampling_; common::ObSArray alloc_op_hints_; + ObDBLinkHit dblink_hints_; }; // used in physical plan diff --git a/src/sql/resolver/dml/ob_sequence_namespace_checker.cpp b/src/sql/resolver/dml/ob_sequence_namespace_checker.cpp index 879b350905..3ae710e585 100644 --- a/src/sql/resolver/dml/ob_sequence_namespace_checker.cpp +++ b/src/sql/resolver/dml/ob_sequence_namespace_checker.cpp @@ -241,9 +241,9 @@ int ObSequenceNamespaceChecker::check_link_sequence_exists(const ObDbLinkSchema exists = false; has_currval = false; dblink_param_ctx param_ctx; + common::ObArenaAllocator allocator; int64_t sql_request_level = 0; uint64_t tenant_id = OB_INVALID_ID; - uint64_t dblink_id = OB_INVALID_ID; DblinkDriverProto link_type = DBLINK_DRV_OB; ObDbLinkProxy *dblink_proxy = GCTX.dblink_proxy_; if (OB_ISNULL(dblink_proxy) || OB_ISNULL(session_info) || OB_ISNULL(dblink_schema)) { @@ -256,23 +256,18 @@ int ObSequenceNamespaceChecker::check_link_sequence_exists(const ObDbLinkSchema } else if (sql_request_level < 1 || sql_request_level > 3) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid sql_request_level", K(sql_request_level), K(ret)); - } else if (!lib::is_oracle_mode() && - OB_FAIL(ObDblinkService::get_set_sql_mode_cstr(session_info, - param_ctx.set_sql_mode_cstr_, - session_info->get_allocator()))) { - LOG_WARN("failed to get sql mode cstr", K(ret)); + } else if (OB_FAIL(ObDblinkService::init_dblink_param_ctx(param_ctx, + session_info, + allocator, //useless in oracle mode + dblink_schema->get_dblink_id(), + static_cast(dblink_schema->get_driver_proto()), + DblinkPoolType::DBLINK_POOL_SCHEMA))) { + LOG_WARN("failed to init dblink param ctx", K(ret), K(param_ctx)); } else { - tenant_id = dblink_schema->get_tenant_id(); - dblink_id = dblink_schema->get_dblink_id(); - link_type = static_cast(dblink_schema->get_driver_proto()); - // don't need set param_ctx.charset_id_ and param_ctx.ncharset_id_, default value is what we need. - param_ctx.pool_type_ = DblinkPoolType::DBLINK_POOL_SCHEMA; - param_ctx.sql_request_level_ = sql_request_level; - param_ctx.tenant_id_ = tenant_id; - param_ctx.dblink_id_ = dblink_id; - param_ctx.link_type_ = link_type; - param_ctx.sessid_ = session_info->get_sessid(); - LOG_DEBUG("get link sequence schema", K(sequence_name), K(database_name), KP(dblink_schema), K(ret)); + // param_ctx.charset_id_ and param_ctx.ncharset_id_, default value is what we need. + param_ctx.charset_id_ = common::ObNlsCharsetId::CHARSET_AL32UTF8_ID; + param_ctx.ncharset_id_ = common::ObNlsCharsetId::CHARSET_AL32UTF8_ID; + LOG_TRACE("get link sequence schema", K(param_ctx), K(sequence_name), K(database_name), KP(dblink_schema), K(ret)); } if (OB_SUCC(ret)) { ObSqlString sql; @@ -305,7 +300,7 @@ int ObSequenceNamespaceChecker::check_link_sequence_exists(const ObDbLinkSchema dblink_schema->get_conn_string(), dblink_schema->get_cluster_name()))) { LOG_WARN("create dblink pool failed", K(ret), K(param_ctx)); - } else if (OB_FAIL(session_info->get_dblink_context().get_dblink_conn(dblink_id, dblink_conn))) { + } else if (OB_FAIL(session_info->get_dblink_context().get_dblink_conn(param_ctx.dblink_id_, dblink_conn))) { LOG_WARN("failed to get dblink connection from session", K(ret)); } else if (NULL == dblink_conn) { if (OB_FAIL(dblink_proxy->acquire_dblink(param_ctx, dblink_conn))) { @@ -314,6 +309,8 @@ int ObSequenceNamespaceChecker::check_link_sequence_exists(const ObDbLinkSchema LOG_WARN("failed to register dblink conn pool to current session", K(ret)); } else if (OB_FAIL(session_info->get_dblink_context().set_dblink_conn(dblink_conn))) { LOG_WARN("failed to set dblink connection to session", K(ret)); + } else if (OB_FAIL(session_info->get_dblink_context().get_dblink_conn(param_ctx.dblink_id_, dblink_conn))) { // will add a rlock on dblink conn, means this dblink_conn is inuse + LOG_WARN("failed to get dblink connection from session", K(ret), K(param_ctx.dblink_id_)); } else { LOG_TRACE("link sequence get connection from dblink pool", K(lbt())); } @@ -354,6 +351,11 @@ int ObSequenceNamespaceChecker::check_link_sequence_exists(const ObDbLinkSchema LOG_WARN("failed to close oci result", K(tmp_ret)); } #endif + // release rlock on dblink_conn + if (OB_SUCCESS != (tmp_ret = ObDblinkCtxInSession::revert_dblink_conn(dblink_conn))) { + LOG_WARN("failed to revert dblink conn", K(tmp_ret), KP(dblink_conn)); + } + dblink_conn = NULL; //release dblink connection by session } } diff --git a/src/sql/resolver/dml/ob_sql_hint.cpp b/src/sql/resolver/dml/ob_sql_hint.cpp index b7ccf769a5..38a03c041b 100644 --- a/src/sql/resolver/dml/ob_sql_hint.cpp +++ b/src/sql/resolver/dml/ob_sql_hint.cpp @@ -675,11 +675,11 @@ int ObQueryHint::print_stmt_hint(PlanText &plan_text, const ObDMLStmt &stmt, if (OB_FAIL(print_outline_data(plan_text))) { LOG_WARN("failed to print outline data", K(ret)); } - } else if (!has_outline_data() || OB_INVALID_ID != stmt.get_dblink_id()) { + } else if (!has_outline_data()) { // Not outline data, print current stmt hint here. // If stmt is the first stmt can add hint, print global hint and hint with qb name. // For query "select_1 union all select_2", root stmt is "union all" and the first stmt to print hint is select_1 - if ((is_first_stmt_for_hint || OB_INVALID_ID != stmt.get_dblink_id()) && + if (is_first_stmt_for_hint && OB_FAIL(get_global_hint().print_global_hint(plan_text))) { LOG_WARN("failed to print global hint", K(ret)); } else if (OB_FAIL(stmt.get_stmt_hint().print_stmt_hint(plan_text))) { diff --git a/src/sql/rewrite/ob_transform_dblink.cpp b/src/sql/rewrite/ob_transform_dblink.cpp index 227eb96552..b64ba90ae5 100644 --- a/src/sql/rewrite/ob_transform_dblink.cpp +++ b/src/sql/rewrite/ob_transform_dblink.cpp @@ -1715,8 +1715,9 @@ int ObTransformDBlink::add_flashback_query_for_dblink(ObDMLStmt *stmt) ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null param", K(ret)); } else if (!table_item->is_link_table() - || TableItem::NOT_USING != table_item->flashback_query_type_) { - // do nothing if not dblink table or already have flashback query + || TableItem::NOT_USING != table_item->flashback_query_type_ + || table_item->has_for_update()) { + // do nothing if not dblink table or already have flashback query or table has for update } else if (FALSE_IT(dblink_id = table_item->dblink_id_)) { } else if (table_item->is_reverse_link_) { need_add = true;