oceanbase/mittest/simple_server/test_big_tx_data.cpp
ZenoWang ccde264e06 [FEAT MERGE] Improve the inner implementation of tx table
Co-authored-by: kongfy <njukongfy@gmail.com>
2023-05-07 07:38:34 +00:00

219 lines
7.7 KiB
C++

#include <chrono>
#include <gtest/gtest.h>
#include <thread>
#define protected public
#define private public
#include "share/ob_table_access_helper.h"
#include "lib/ob_define.h"
#include "observer/ob_server_struct.h"
#include "share/rc/ob_tenant_base.h"
#include "storage/ls/ob_ls_meta.h"
#include "storage/ls/ob_ls.h"
#include "storage/tx_storage/ob_ls_service.h"
#include "env/ob_simple_cluster_test_base.h"
#include "lib/mysqlclient/ob_mysql_result.h"
#include "storage/tx_storage/ob_ls_handle.h"
#include <iostream>
#include "rewrite_function_for_test_big_tx_data.cpp"
using namespace std;
namespace oceanbase
{
using namespace storage;
namespace unittest
{
using namespace oceanbase::transaction;
using namespace oceanbase::storage;
class TestRunCtx
{
public:
uint64_t tenant_id_ = 0;
int time_sec_ = 0;
};
TestRunCtx RunCtx;
class TestBigTxData : public ObSimpleClusterTestBase
{
public:
// 指定case运行目录前缀 test_ob_simple_cluster_
void minor_freeze_and_wait();
TestBigTxData() : ObSimpleClusterTestBase("test_big_tx_data_") {}
};
#define DO(stmt) /*cout << "before do line:" << __LINE__ << endl;*/ASSERT_EQ((stmt), OB_SUCCESS);/*cout << "after do line:" << __LINE__ << endl;*/
#define EXEC_SQL(sql) connection->execute_write(OB_SYS_TENANT_ID, sql, affected_rows)
class DoNothingOP : public ObITxDataCheckFunctor
{
virtual int operator()(const ObTxData &tx_data, ObTxCCCtx *tx_cc_ctx = nullptr) {
UNUSED(tx_cc_ctx);
cout << "read tx data:" << tx_data.tx_id_.get_id() << ", undo cnt:" << tx_data.undo_status_list_.undo_node_cnt_ << endl;
STORAGE_LOG_RET(INFO, 0, "read tx data", K(tx_data.tx_id_), K(lbt()));
return OB_SUCCESS;
}
};
TEST_F(TestBigTxData, big_tx_data)
{
int ret = OB_SUCCESS;
MTL_SWITCH(OB_SYS_TENANT_ID) {
int64_t affected_rows = 0;
sqlclient::ObISQLConnection *connection = nullptr;
// 1,开启事务,生成一些savepoint
ASSERT_EQ(OB_SUCCESS, get_curr_simple_server().get_sql_proxy().acquire(connection));
DO(EXEC_SQL("set ob_trx_timeout = 6000000000"));
DO(EXEC_SQL("set ob_trx_idle_timeout = 6000000000"));
DO(EXEC_SQL("alter system set _fast_commit_callback_count = 0"));// disallow fast commit
DO(EXEC_SQL("create table test_big_tx_data (a int primary key, b int)"));
DO(EXEC_SQL("alter system set _private_buffer_size = '1B'"));
DO(EXEC_SQL("begin"));
constexpr int64_t savepoint_size = 12;
for (int64_t idx = 0; idx < savepoint_size; ++idx) {
ObSqlString sql;
DO(sql.append_fmt("insert into test_big_tx_data values(%ld, 1)", idx));
DO(EXEC_SQL(sql.ptr()));
sql.reset();
DO(sql.append_fmt("savepoint s%ld", idx));
DO(EXEC_SQL(sql.ptr()));
}
// 2,获取本事务ID,这个事务的tx data足够大
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
int64_t sess_id = 0;
int64_t tx_id;
DO(connection->execute_read(OB_SYS_TENANT_ID, "select connection_id()", res));
common::sqlclient::ObMySQLResult *result = res.mysql_result();
DO(result->next());
result->get_int("connection_id()", sess_id);
ObSqlString sql;
DO(sql.append_fmt("select trans_id from oceanbase.__all_virtual_processlist where id=%ld", sess_id));
res.reset();
DO(connection->execute_read(OB_SYS_TENANT_ID, sql.ptr(), res));
result = res.mysql_result();
DO(result->next());
result->get_int("trans_id", tx_id);
ASSERT_EQ(OB_ITER_END, result->next());
ATOMIC_STORE(&TEST_TX_ID, tx_id);
std::cout << "tx_id:" << tx_id << std::endl;
}
// 3,写日志才可以生成undo status
cout << "alter system minor freeze 1" << endl;
minor_freeze_and_wait();
// 4,回滚生成undo status
for (int64_t idx = savepoint_size - 1; idx >= 0; --idx) {
ObSqlString sql;
DO(sql.append_fmt("rollback to s%ld", idx));
DO(EXEC_SQL(sql.ptr()));
}
DO(EXEC_SQL("commit"));
::sleep(10);
// 5,把tx data转下去
cout << "alter system minor freeze 2" << endl;
minor_freeze_and_wait();
ASSERT_EQ(ATOMIC_LOAD(&DUMP_BIG_TX_DATA), true);// 确保tx data已经走过了序列化逻辑
// 6, 读一次这个tx data
DoNothingOP op;
ObLSService *ls_service = MTL(ObLSService*);
ObLSHandle handle;
DO(ls_service->get_ls(ObLSID(1), handle, storage::ObLSGetMod::DEADLOCK_MOD));
fprintf(stdout, "start read tx data from sstable, test_tx_id = %ld\n", TEST_TX_ID);
ObTxDataMiniCache fake_cache;
ObReadTxDataArg read_arg(ObTransID(ATOMIC_LOAD(&TEST_TX_ID)), 0, fake_cache);
DO(handle.get_ls()->tx_table_.check_with_tx_data(read_arg, op));
// 7,检查被测事务的tx data已经经过了deserialize
ASSERT_EQ(ATOMIC_LOAD(&LOAD_BIG_TX_DATA), true);
}
}
void TestBigTxData::minor_freeze_and_wait()
{
int ret = OB_SUCCESS;
MTL_SWITCH(OB_SYS_TENANT_ID) {
int64_t affected_rows = 0;
int64_t retry_times = 40;
ObLSService *ls_service = MTL(ObLSService*);
ObLSHandle handle;
DO(ls_service->get_ls(ObLSID(1), handle, storage::ObLSGetMod::DEADLOCK_MOD));
ObTxDataMemtableMgr *mgr = handle.get_ls()->tx_table_.tx_data_table_.memtable_mgr_;
ASSERT_NE(nullptr, mgr);
int64_t head_before_freeze = -1;
int64_t tail_before_freeze = -1;
int64_t head_after_freeze = -1;
int64_t tail_after_freeze = -1;
while (--retry_times > 0) {
DO(mgr->get_memtable_range(head_before_freeze, tail_before_freeze));
ASSERT_GE(head_before_freeze, 0);
ASSERT_GE(tail_before_freeze, 0);
if (head_before_freeze + 1 != tail_before_freeze) {
::sleep(1);
cout << "waiting last minor freeze done ... "
<< "head_before_freeze = " << head_before_freeze << " tail_before_freeze = " << tail_before_freeze << endl;
} else {
break;
}
}
ASSERT_EQ(head_before_freeze + 1, tail_before_freeze);
cout << "head_before_freeze : " << head_before_freeze << " tail_before_freeze" << tail_before_freeze << endl;
// minor freeze once
DO(get_curr_simple_server().get_sql_proxy().write("alter system minor freeze", affected_rows));
retry_times = 60;
while (--retry_times > 0)
{
DO(handle.get_ls()->tx_table_.tx_data_table_.memtable_mgr_->get_memtable_range(head_after_freeze, tail_after_freeze));
ASSERT_GE(head_after_freeze, 0);
ASSERT_GE(tail_after_freeze, 0);
if (head_after_freeze > head_before_freeze && tail_after_freeze > tail_before_freeze && head_after_freeze + 1 == tail_after_freeze) {
fprintf(stdout,
"head_after_freeze : %ld, head_before_freeze : %ld, tail_after_freeze : %ld, tail_before_freeze : %ld\n",
head_after_freeze,
head_before_freeze,
tail_after_freeze,
tail_before_freeze);
break;
} else {
::sleep(1);
cout << "waiting this minor freeze done, head_after_freeze: " << head_after_freeze << " tail_after_freeze " << tail_after_freeze << endl;
}
}
ASSERT_GT(head_after_freeze, head_before_freeze);
ASSERT_GT(tail_after_freeze, tail_before_freeze);
ASSERT_EQ(head_after_freeze + 1, tail_after_freeze);
}
}
} // end unittest
} // end oceanbase
int main(int argc, char **argv)
{
int c = 0;
int time_sec = 0;
char *log_level = (char*)"INFO";
while(EOF != (c = getopt(argc,argv,"t:l:"))) {
switch(c) {
case 't':
time_sec = atoi(optarg);
break;
case 'l':
log_level = optarg;
oceanbase::unittest::ObSimpleClusterTestBase::enable_env_warn_log_ = false;
break;
default:
break;
}
}
oceanbase::unittest::init_log_and_gtest(argc, argv);
OB_LOGGER.set_log_level(log_level);
oceanbase::unittest::RunCtx.time_sec_ = time_sec;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}