diff --git a/src/storage/tablelock/ob_obj_lock.cpp b/src/storage/tablelock/ob_obj_lock.cpp index 325257ccb9..b64097a316 100644 --- a/src/storage/tablelock/ob_obj_lock.cpp +++ b/src/storage/tablelock/ob_obj_lock.cpp @@ -166,7 +166,7 @@ int ObOBJLock::recover_( return ret; } -int ObOBJLock::lock_( +int ObOBJLock::slow_lock( const ObLockParam ¶m, const ObTableLockOp &lock_op, const ObTableLockMode &lock_mode_in_same_trans, @@ -186,6 +186,7 @@ int ObOBJLock::lock_( ObMemAttr attr(tenant_id, "ObTableLockOp"); // 1. check lock conflict. // 2. record lock op. + WRLockGuard guard(rwlock_); if (is_deleted_) { ret = OB_EAGAIN; need_retry = false; @@ -197,12 +198,6 @@ int ObOBJLock::lock_( if (OB_TRY_LOCK_ROW_CONFLICT != ret) { LOG_WARN("check allow lock failed", K(ret), K(lock_op)); } - } else if (OB_LIKELY(!lock_op.need_record_lock_op())) { - if (lock_op.lock_mode_ == ROW_EXCLUSIVE) { - lock_row_exclusive_(); - } else if (lock_op.lock_mode_ == ROW_SHARE) { - lock_row_share_(); - } } else if (OB_FAIL(get_or_create_op_list(lock_op.lock_mode_, tenant_id, allocator, @@ -416,6 +411,96 @@ int ObOBJLock::update_lock_status(const ObTableLockOp &lock_op, return ret; } +int ObOBJLock::try_fast_lock_( + const ObTableLockOp &lock_op, + const ObTableLockMode &lock_mode_in_same_trans, + bool &need_retry, + ObTxIDSet &conflict_tx_set) +{ + int ret = OB_SUCCESS; + bool unused_conflict_with_dml_lock = false; + if (is_deleted_) { + ret = OB_EAGAIN; + need_retry = false; + } else if (OB_UNLIKELY(lock_op.need_record_lock_op())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("this lock op should not do fast lock", KR(ret), K(lock_op)); + } else if (OB_FAIL(check_allow_lock_(lock_op, + lock_mode_in_same_trans, + conflict_tx_set, + unused_conflict_with_dml_lock))) { + if (OB_TRY_LOCK_ROW_CONFLICT != ret) { + LOG_WARN("check allow lock failed", K(ret), K(lock_op)); + } + } else { + if (lock_op.lock_mode_ == ROW_EXCLUSIVE) { + lock_row_exclusive_(); + } else if (lock_op.lock_mode_ == ROW_SHARE) { + lock_row_share_(); + } + LOG_DEBUG("succeed create lock ", K(lock_op)); + } + return ret; +} + +int ObOBJLock::fast_lock( + const ObLockParam ¶m, + const ObTableLockOp &lock_op, + const ObTableLockMode &lock_mode_in_same_trans, + bool &need_retry, + ObMalloc &allocator, + ObTxIDSet &conflict_tx_set) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + bool is_compacted = false; + const bool is_force_compact = true; + { + // lock first time + RDLockGuard guard(rwlock_); + if (OB_FAIL(try_fast_lock_(lock_op, + lock_mode_in_same_trans, + need_retry, + conflict_tx_set))) { + if (OB_TRY_LOCK_ROW_CONFLICT != ret) { + LOG_WARN("try fast lock failed", KR(ret), K(lock_op)); + } + } else { + LOG_DEBUG("succeed create lock ", K(lock_op)); + } + } + // compact if need. + if (OB_TRY_LOCK_ROW_CONFLICT == ret) { + WRLockGuard guard(rwlock_); + if (is_deleted_) { + ret = OB_EAGAIN; + need_retry = false; + } else if(OB_TMP_FAIL(compact_tablelock_(allocator, is_compacted, is_force_compact))) { + // compact the obj lock to make sure the lock op that need compact will + // not block the lock operation next time. + LOG_WARN("compact tablelock failed", K(tmp_ret), K(lock_op)); + } + } + if (OB_TRY_LOCK_ROW_CONFLICT == ret && is_compacted) { + RDLockGuard guard(rwlock_); + if (OB_FAIL(try_fast_lock_(lock_op, + lock_mode_in_same_trans, + need_retry, + conflict_tx_set))) { + if (OB_TRY_LOCK_ROW_CONFLICT != ret) { + LOG_WARN("try fast lock failed", KR(ret), K(lock_op)); + } + } else { + LOG_DEBUG("succeed create lock ", K(lock_op)); + } + } + // 1. need retry basic conditions + if (ret == OB_TRY_LOCK_ROW_CONFLICT && !param.is_try_lock_) { + need_retry = true; + } + return ret; +} + int ObOBJLock::lock( const ObLockParam ¶m, ObStoreCtx &ctx, @@ -438,34 +523,28 @@ int ObOBJLock::lock( bool need_retry = false; do { need_retry = false; - { - if (OB_LIKELY(!lock_op.need_record_lock_op())) { - RDLockGuard guard(rwlock_); - if (OB_FAIL(lock_(param, - lock_op, - lock_mode_in_same_trans, - need_retry, - allocator, - conflict_tx_set))) { - if (ret != OB_TRY_LOCK_ROW_CONFLICT && - ret != OB_EAGAIN) { - LOG_WARN("lock failed.", K(ret), K(lock_op)); - } - } - } else { - WRLockGuard guard(rwlock_); - if (OB_FAIL(lock_(param, - lock_op, - lock_mode_in_same_trans, - need_retry, - allocator, - conflict_tx_set))) { - if (ret != OB_TRY_LOCK_ROW_CONFLICT && - ret != OB_EAGAIN) { - LOG_WARN("lock failed.", K(ret), K(lock_op)); - } + if (OB_LIKELY(!lock_op.need_record_lock_op())) { + if (OB_FAIL(fast_lock(param, + lock_op, + lock_mode_in_same_trans, + need_retry, + allocator, + conflict_tx_set))) { + if (ret != OB_TRY_LOCK_ROW_CONFLICT && + ret != OB_EAGAIN) { + LOG_WARN("lock failed.", K(ret), K(lock_op)); } } + } else if (OB_FAIL(slow_lock(param, + lock_op, + lock_mode_in_same_trans, + need_retry, + allocator, + conflict_tx_set))) { + if (ret != OB_TRY_LOCK_ROW_CONFLICT && + ret != OB_EAGAIN) { + LOG_WARN("lock failed.", K(ret), K(lock_op)); + } } if (need_retry && @@ -934,22 +1013,48 @@ int ObOBJLock::check_allow_lock( const ObTableLockMode &lock_mode_in_same_trans, ObTxIDSet &conflict_tx_set, bool &conflict_with_dml_lock, + ObMalloc &allocator, const bool include_finish_tx, const bool only_check_dml_lock) { int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + bool is_compacted = false; + const bool is_force_compact = true; if (OB_UNLIKELY(!lock_op.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument.", K(ret), K(lock_op)); } else { // prevent from create new lock op. - RDLockGuard guard(rwlock_); - ret = check_allow_lock_(lock_op, - lock_mode_in_same_trans, - conflict_tx_set, - conflict_with_dml_lock, - include_finish_tx, - only_check_dml_lock); + // may be we need compact the lock. + { + RDLockGuard guard(rwlock_); + ret = check_allow_lock_(lock_op, + lock_mode_in_same_trans, + conflict_tx_set, + conflict_with_dml_lock, + include_finish_tx, + only_check_dml_lock); + } + // compact if need. + if (OB_TRY_LOCK_ROW_CONFLICT == ret) { + WRLockGuard guard(rwlock_); + if(OB_TMP_FAIL(compact_tablelock_(allocator, is_compacted, is_force_compact))) { + // compact the obj lock to make sure the lock op that need compact will + // not block the lock operation next time. + LOG_WARN("compact tablelock failed", K(tmp_ret), K(lock_op)); + } + } + // recheck if compacted + if (OB_TRY_LOCK_ROW_CONFLICT == ret && is_compacted) { + RDLockGuard guard(rwlock_); + ret = check_allow_lock_(lock_op, + lock_mode_in_same_trans, + conflict_tx_set, + conflict_with_dml_lock, + include_finish_tx, + only_check_dml_lock); + } } return ret; } @@ -2042,6 +2147,7 @@ int ObOBJLockMap::check_allow_lock( lock_mode_in_same_trans, conflict_tx_set, conflict_with_dml_lock, + allocator_, include_finish_tx, only_check_dml_lock))) { if (OB_TRY_LOCK_ROW_CONFLICT != ret) { diff --git a/src/storage/tablelock/ob_obj_lock.h b/src/storage/tablelock/ob_obj_lock.h index 4a48279ffe..2a071ba3c0 100644 --- a/src/storage/tablelock/ob_obj_lock.h +++ b/src/storage/tablelock/ob_obj_lock.h @@ -114,6 +114,7 @@ public: const ObTableLockMode &lock_mode_in_same_trans, ObTxIDSet &conflict_tx_set, bool &conflict_with_dml_lock, + ObMalloc &allocator, const bool include_finish_tx = true, const bool only_check_dml_lock = false); share::SCN get_min_ddl_lock_committed_scn(const share::SCN &flushed_scn) const; @@ -161,13 +162,25 @@ private: int recover_( const ObTableLockOp &lock_op, ObMalloc &allocator); - int lock_( + int fast_lock( const ObLockParam ¶m, const ObTableLockOp &lock_op, const ObTableLockMode &lock_mode_in_same_trans, bool &need_retry, ObMalloc &allocator, ObTxIDSet &conflict_tx_set); + int slow_lock( + const ObLockParam ¶m, + const ObTableLockOp &lock_op, + const ObTableLockMode &lock_mode_in_same_trans, + bool &need_retry, + ObMalloc &allocator, + ObTxIDSet &conflict_tx_set); + int try_fast_lock_( + const ObTableLockOp &lock_op, + const ObTableLockMode &lock_mode_in_same_trans, + bool &need_retry, + ObTxIDSet &conflict_tx_set); int unlock_( const ObTableLockOp &unlock_op, ObMalloc &allocator); diff --git a/tools/ob_admin/server_tool/ob_admin_routine.cpp b/tools/ob_admin/server_tool/ob_admin_routine.cpp index c9bfaf0507..616bede918 100644 --- a/tools/ob_admin/server_tool/ob_admin_routine.cpp +++ b/tools/ob_admin/server_tool/ob_admin_routine.cpp @@ -626,7 +626,7 @@ DEF_COMMAND(TRANS, remove_lock, 1, "tenant_id ls_id obj_type obj_id lock_mode ow } if (OB_FAIL(ret)) { - } else if (12 != sscanf(arg_str.c_str(), + } else if (8 != sscanf(arg_str.c_str(), "%ld %ld %ld %ld %ld %ld %ld %ld", &tenant_id_to_set, &ls_id_to_set, &obj_type, &obj_id, &lock_mode, &owner_id, &create_tx_id, &op_type)) {