[4.1] add flag to protect batch update

This commit is contained in:
Handora
2023-02-09 14:26:17 +00:00
committed by ob-robot
parent 3f8bc6dd73
commit 8ee348c40d
3 changed files with 93 additions and 66 deletions

View File

@ -1019,6 +1019,9 @@ int ObDMLService::init_dml_param(const ObDASDMLBaseCtDef &base_ctdef,
dml_param.is_batch_stmt_ = base_ctdef.is_batch_stmt_;
dml_param.dml_allocator_ = &das_alloc;
dml_param.snapshot_ = snapshot;
if (base_ctdef.is_batch_stmt_) {
dml_param.write_flag_.set_is_dml_batch_opt();
}
return ret;
}

View File

@ -53,11 +53,17 @@ int check_sequence_set_violation(const concurrent_control::ObWriteFlag write_fla
// example, add the lob flag for the case 2.1 to prevent the other scenes from
// happening.
if (writer_tx_id == locker_tx_id
if (writer_tx_id == locker_tx_id) {
// We need guarantee the right sequence of the same txn operations
if (writer_seq_no < locker_seq_no) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(ERROR, "wrong row of sequence on one row found", K(reader_seq_no),
K(writer_tx_id), K(writer_dml_flag), K(writer_seq_no),
K(locker_tx_id), K(locker_dml_flag), K(locker_seq_no));
// For statements during sql and threads during PDML, the following rules is
// guaranteed:
// 1. reader seq no is bigger or equal than the seq no of the last statements
&& reader_seq_no < locker_seq_no) {
} else if (reader_seq_no < locker_seq_no) {
// Case 1: It may happens that two pdml unique index tasks insert the same
// row concurrently, so we report duplicate key under the case to prevent
// the insertion.
@ -114,8 +120,19 @@ int check_sequence_set_violation(const concurrent_control::ObWriteFlag write_fla
} else if (blocksstable::ObDmlFlag::DF_DELETE == writer_dml_flag
&& blocksstable::ObDmlFlag::DF_DELETE == locker_dml_flag) {
// bypass the case
// Case 7: For the case of batch dml operation, it may operate the same row
// concurrently if the first operation has no effects.(SQL layer will check
// the modification of the row before the second operation, and report the
// error if the row has been modified while the first row may have no effect
// and the parallel insert may happen). So we need report the batched stmt
// warning according to this case.
} else if (write_flag.is_dml_batch_opt()) {
ret = OB_BATCHED_MULTI_STMT_ROLLBACK;
TRANS_LOG(WARN, "batch multi stmt rollback found", K(ret),
K(writer_tx_id), K(writer_dml_flag), K(writer_seq_no),
K(locker_tx_id), K(locker_dml_flag), K(locker_seq_no));
} else {
// Case 7: It will never happen that two operaions on the same row for the
// Others: It will never happen that two operaions on the same row for the
// same txn except the above cases. So we should report unexpected error.
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(ERROR, "multiple modification on one row found", K(reader_seq_no),
@ -123,6 +140,7 @@ int check_sequence_set_violation(const concurrent_control::ObWriteFlag write_fla
K(locker_tx_id), K(locker_dml_flag), K(locker_seq_no));
}
}
}
return ret;
}

View File

@ -27,11 +27,13 @@ struct ObWriteFlag
#define OBWF_BIT_TABLE_API 1
#define OBWF_BIT_TABLE_LOCK 1
#define OBWF_BIT_MDS 1
#define OBWF_BIT_DML_BATCH_OPT 1
#define OBWF_BIT_RESERVED 61
static const uint64_t OBWF_MASK_TABLE_API = (0x1UL << OBWF_BIT_TABLE_API) - 1;
static const uint64_t OBWF_MASK_TABLE_LOCK = (0x1UL << OBWF_BIT_TABLE_LOCK) - 1;
static const uint64_t OBWF_MASK_MDS = (0x1UL << OBWF_BIT_MDS) - 1;
static const uint64_t OBWF_MASK_DML_BATCH_OPT = (0x1UL << OBWF_BIT_DML_BATCH_OPT) - 1;
union
{
@ -41,6 +43,7 @@ struct ObWriteFlag
uint64_t is_table_api_ : OBWF_BIT_TABLE_API; // 0: false(default), 1: true
uint64_t is_table_lock_ : OBWF_BIT_TABLE_LOCK; // 0: false(default), 1: true
uint64_t is_mds_ : OBWF_BIT_MDS; // 0: false(default), 1: true
uint64_t is_dml_batch_opt_ : OBWF_BIT_DML_BATCH_OPT; // 0: false(default), 1: true
uint64_t reserved_ : OBWF_BIT_RESERVED;
};
};
@ -53,10 +56,13 @@ struct ObWriteFlag
inline void set_is_table_lock() { is_table_lock_ = true; }
inline bool is_mds() const { return is_mds_; }
inline void set_is_mds() { is_mds_ = true; }
inline bool is_dml_batch_opt() const { return is_dml_batch_opt_; }
inline void set_is_dml_batch_opt() { is_dml_batch_opt_ = true; }
TO_STRING_KV("is_table_api", is_table_api_,
"is_table_lock", is_table_lock_,
"is_mds", is_mds_);
"is_mds", is_mds_,
"is_dml_batch_opt", is_dml_batch_opt_);
OB_UNIS_VERSION(1);
};