BUGFIX: fix tablelock core
This commit is contained in:
@ -166,7 +166,7 @@ int ObOBJLock::recover_(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObOBJLock::lock_(
|
int ObOBJLock::slow_lock(
|
||||||
const ObLockParam ¶m,
|
const ObLockParam ¶m,
|
||||||
const ObTableLockOp &lock_op,
|
const ObTableLockOp &lock_op,
|
||||||
const ObTableLockMode &lock_mode_in_same_trans,
|
const ObTableLockMode &lock_mode_in_same_trans,
|
||||||
@ -186,6 +186,7 @@ int ObOBJLock::lock_(
|
|||||||
ObMemAttr attr(tenant_id, "ObTableLockOp");
|
ObMemAttr attr(tenant_id, "ObTableLockOp");
|
||||||
// 1. check lock conflict.
|
// 1. check lock conflict.
|
||||||
// 2. record lock op.
|
// 2. record lock op.
|
||||||
|
WRLockGuard guard(rwlock_);
|
||||||
if (is_deleted_) {
|
if (is_deleted_) {
|
||||||
ret = OB_EAGAIN;
|
ret = OB_EAGAIN;
|
||||||
need_retry = false;
|
need_retry = false;
|
||||||
@ -197,12 +198,6 @@ int ObOBJLock::lock_(
|
|||||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
||||||
LOG_WARN("check allow lock failed", K(ret), K(lock_op));
|
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_,
|
} else if (OB_FAIL(get_or_create_op_list(lock_op.lock_mode_,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
allocator,
|
allocator,
|
||||||
@ -416,6 +411,96 @@ int ObOBJLock::update_lock_status(const ObTableLockOp &lock_op,
|
|||||||
return ret;
|
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(
|
int ObOBJLock::lock(
|
||||||
const ObLockParam ¶m,
|
const ObLockParam ¶m,
|
||||||
ObStoreCtx &ctx,
|
ObStoreCtx &ctx,
|
||||||
@ -438,10 +523,8 @@ int ObOBJLock::lock(
|
|||||||
bool need_retry = false;
|
bool need_retry = false;
|
||||||
do {
|
do {
|
||||||
need_retry = false;
|
need_retry = false;
|
||||||
{
|
|
||||||
if (OB_LIKELY(!lock_op.need_record_lock_op())) {
|
if (OB_LIKELY(!lock_op.need_record_lock_op())) {
|
||||||
RDLockGuard guard(rwlock_);
|
if (OB_FAIL(fast_lock(param,
|
||||||
if (OB_FAIL(lock_(param,
|
|
||||||
lock_op,
|
lock_op,
|
||||||
lock_mode_in_same_trans,
|
lock_mode_in_same_trans,
|
||||||
need_retry,
|
need_retry,
|
||||||
@ -452,9 +535,7 @@ int ObOBJLock::lock(
|
|||||||
LOG_WARN("lock failed.", K(ret), K(lock_op));
|
LOG_WARN("lock failed.", K(ret), K(lock_op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (OB_FAIL(slow_lock(param,
|
||||||
WRLockGuard guard(rwlock_);
|
|
||||||
if (OB_FAIL(lock_(param,
|
|
||||||
lock_op,
|
lock_op,
|
||||||
lock_mode_in_same_trans,
|
lock_mode_in_same_trans,
|
||||||
need_retry,
|
need_retry,
|
||||||
@ -465,8 +546,6 @@ int ObOBJLock::lock(
|
|||||||
LOG_WARN("lock failed.", K(ret), K(lock_op));
|
LOG_WARN("lock failed.", K(ret), K(lock_op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_retry &&
|
if (need_retry &&
|
||||||
ret == OB_TRY_LOCK_ROW_CONFLICT) {
|
ret == OB_TRY_LOCK_ROW_CONFLICT) {
|
||||||
@ -934,15 +1013,21 @@ int ObOBJLock::check_allow_lock(
|
|||||||
const ObTableLockMode &lock_mode_in_same_trans,
|
const ObTableLockMode &lock_mode_in_same_trans,
|
||||||
ObTxIDSet &conflict_tx_set,
|
ObTxIDSet &conflict_tx_set,
|
||||||
bool &conflict_with_dml_lock,
|
bool &conflict_with_dml_lock,
|
||||||
|
ObMalloc &allocator,
|
||||||
const bool include_finish_tx,
|
const bool include_finish_tx,
|
||||||
const bool only_check_dml_lock)
|
const bool only_check_dml_lock)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
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())) {
|
if (OB_UNLIKELY(!lock_op.is_valid())) {
|
||||||
ret = OB_INVALID_ARGUMENT;
|
ret = OB_INVALID_ARGUMENT;
|
||||||
LOG_WARN("invalid argument.", K(ret), K(lock_op));
|
LOG_WARN("invalid argument.", K(ret), K(lock_op));
|
||||||
} else {
|
} else {
|
||||||
// prevent from create new lock op.
|
// prevent from create new lock op.
|
||||||
|
// may be we need compact the lock.
|
||||||
|
{
|
||||||
RDLockGuard guard(rwlock_);
|
RDLockGuard guard(rwlock_);
|
||||||
ret = check_allow_lock_(lock_op,
|
ret = check_allow_lock_(lock_op,
|
||||||
lock_mode_in_same_trans,
|
lock_mode_in_same_trans,
|
||||||
@ -951,6 +1036,26 @@ int ObOBJLock::check_allow_lock(
|
|||||||
include_finish_tx,
|
include_finish_tx,
|
||||||
only_check_dml_lock);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2042,6 +2147,7 @@ int ObOBJLockMap::check_allow_lock(
|
|||||||
lock_mode_in_same_trans,
|
lock_mode_in_same_trans,
|
||||||
conflict_tx_set,
|
conflict_tx_set,
|
||||||
conflict_with_dml_lock,
|
conflict_with_dml_lock,
|
||||||
|
allocator_,
|
||||||
include_finish_tx,
|
include_finish_tx,
|
||||||
only_check_dml_lock))) {
|
only_check_dml_lock))) {
|
||||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
||||||
|
|||||||
@ -114,6 +114,7 @@ public:
|
|||||||
const ObTableLockMode &lock_mode_in_same_trans,
|
const ObTableLockMode &lock_mode_in_same_trans,
|
||||||
ObTxIDSet &conflict_tx_set,
|
ObTxIDSet &conflict_tx_set,
|
||||||
bool &conflict_with_dml_lock,
|
bool &conflict_with_dml_lock,
|
||||||
|
ObMalloc &allocator,
|
||||||
const bool include_finish_tx = true,
|
const bool include_finish_tx = true,
|
||||||
const bool only_check_dml_lock = false);
|
const bool only_check_dml_lock = false);
|
||||||
share::SCN get_min_ddl_lock_committed_scn(const share::SCN &flushed_scn) const;
|
share::SCN get_min_ddl_lock_committed_scn(const share::SCN &flushed_scn) const;
|
||||||
@ -161,13 +162,25 @@ private:
|
|||||||
int recover_(
|
int recover_(
|
||||||
const ObTableLockOp &lock_op,
|
const ObTableLockOp &lock_op,
|
||||||
ObMalloc &allocator);
|
ObMalloc &allocator);
|
||||||
int lock_(
|
int fast_lock(
|
||||||
const ObLockParam ¶m,
|
const ObLockParam ¶m,
|
||||||
const ObTableLockOp &lock_op,
|
const ObTableLockOp &lock_op,
|
||||||
const ObTableLockMode &lock_mode_in_same_trans,
|
const ObTableLockMode &lock_mode_in_same_trans,
|
||||||
bool &need_retry,
|
bool &need_retry,
|
||||||
ObMalloc &allocator,
|
ObMalloc &allocator,
|
||||||
ObTxIDSet &conflict_tx_set);
|
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_(
|
int unlock_(
|
||||||
const ObTableLockOp &unlock_op,
|
const ObTableLockOp &unlock_op,
|
||||||
ObMalloc &allocator);
|
ObMalloc &allocator);
|
||||||
|
|||||||
@ -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)) {
|
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",
|
"%ld %ld %ld %ld %ld %ld %ld %ld",
|
||||||
&tenant_id_to_set, &ls_id_to_set, &obj_type,
|
&tenant_id_to_set, &ls_id_to_set, &obj_type,
|
||||||
&obj_id, &lock_mode, &owner_id, &create_tx_id, &op_type)) {
|
&obj_id, &lock_mode, &owner_id, &create_tx_id, &op_type)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user