提交 2624ea65 编写于 作者: S Shengliang Guan

fix: add pre-finished stage, trans won't be dropped in follower if it has undo...

fix: add pre-finished stage, trans won't be dropped in follower if it has undo actions while rollback
上级 ff70b102
...@@ -108,7 +108,8 @@ typedef enum { ...@@ -108,7 +108,8 @@ typedef enum {
TRN_STAGE_UNDO_ACTION = 3, TRN_STAGE_UNDO_ACTION = 3,
TRN_STAGE_COMMIT = 4, TRN_STAGE_COMMIT = 4,
TRN_STAGE_COMMIT_ACTION = 5, TRN_STAGE_COMMIT_ACTION = 5,
TRN_STAGE_FINISHED = 6 TRN_STAGE_FINISHED = 6,
TRN_STAGE_PRE_FINISH = 7
} ETrnStage; } ETrnStage;
typedef enum { typedef enum {
......
...@@ -460,6 +460,8 @@ static const char *mndTransStr(ETrnStage stage) { ...@@ -460,6 +460,8 @@ static const char *mndTransStr(ETrnStage stage) {
return "commitAction"; return "commitAction";
case TRN_STAGE_FINISHED: case TRN_STAGE_FINISHED:
return "finished"; return "finished";
case TRN_STAGE_PRE_FINISH:
return "pre-finish";
default: default:
return "invalid"; return "invalid";
} }
...@@ -602,6 +604,11 @@ static int32_t mndTransActionUpdate(SSdb *pSdb, STrans *pOld, STrans *pNew) { ...@@ -602,6 +604,11 @@ static int32_t mndTransActionUpdate(SSdb *pSdb, STrans *pOld, STrans *pNew) {
mTrace("trans:%d, stage from rollback to undoAction since perform update action", pNew->id); mTrace("trans:%d, stage from rollback to undoAction since perform update action", pNew->id);
} }
if (pOld->stage == TRN_STAGE_PRE_FINISH) {
pOld->stage = TRN_STAGE_FINISHED;
mTrace("trans:%d, stage from pre-finish to finished since perform update action", pNew->id);
}
return 0; return 0;
} }
...@@ -931,6 +938,16 @@ static int32_t mndTransRollback(SMnode *pMnode, STrans *pTrans) { ...@@ -931,6 +938,16 @@ static int32_t mndTransRollback(SMnode *pMnode, STrans *pTrans) {
return 0; return 0;
} }
static int32_t mndTransPreFinish(SMnode *pMnode, STrans *pTrans) {
mInfo("trans:%d, pre-finish transaction", pTrans->id);
if (mndTransSync(pMnode, pTrans) != 0) {
mError("trans:%d, failed to pre-finish since %s", pTrans->id, terrstr());
return -1;
}
mInfo("trans:%d, pre-finish finished", pTrans->id);
return 0;
}
static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) { static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) {
bool sendRsp = false; bool sendRsp = false;
int32_t code = pTrans->code; int32_t code = pTrans->code;
...@@ -1437,7 +1454,7 @@ static bool mndTransPerformCommitActionStage(SMnode *pMnode, STrans *pTrans) { ...@@ -1437,7 +1454,7 @@ static bool mndTransPerformCommitActionStage(SMnode *pMnode, STrans *pTrans) {
if (code == 0) { if (code == 0) {
pTrans->code = 0; pTrans->code = 0;
pTrans->stage = TRN_STAGE_FINISHED; pTrans->stage = TRN_STAGE_FINISHED; // TRN_STAGE_PRE_FINISH is not necessary
mInfo("trans:%d, stage from commitAction to finished", pTrans->id); mInfo("trans:%d, stage from commitAction to finished", pTrans->id);
continueExec = true; continueExec = true;
} else { } else {
...@@ -1455,8 +1472,8 @@ static bool mndTransPerformUndoActionStage(SMnode *pMnode, STrans *pTrans) { ...@@ -1455,8 +1472,8 @@ static bool mndTransPerformUndoActionStage(SMnode *pMnode, STrans *pTrans) {
int32_t code = mndTransExecuteUndoActions(pMnode, pTrans); int32_t code = mndTransExecuteUndoActions(pMnode, pTrans);
if (code == 0) { if (code == 0) {
pTrans->stage = TRN_STAGE_FINISHED; pTrans->stage = TRN_STAGE_PRE_FINISH;
mInfo("trans:%d, stage from undoAction to finished", pTrans->id); mInfo("trans:%d, stage from undoAction to pre-finish", pTrans->id);
continueExec = true; continueExec = true;
} else if (code == TSDB_CODE_ACTION_IN_PROGRESS) { } else if (code == TSDB_CODE_ACTION_IN_PROGRESS) {
mInfo("trans:%d, stage keep on undoAction since %s", pTrans->id, tstrerror(code)); mInfo("trans:%d, stage keep on undoAction since %s", pTrans->id, tstrerror(code));
...@@ -1489,6 +1506,25 @@ static bool mndTransPerformRollbackStage(SMnode *pMnode, STrans *pTrans) { ...@@ -1489,6 +1506,25 @@ static bool mndTransPerformRollbackStage(SMnode *pMnode, STrans *pTrans) {
return continueExec; return continueExec;
} }
static bool mndTransPerfromPreFinishedStage(SMnode *pMnode, STrans *pTrans) {
if (mndCannotExecuteTransAction(pMnode)) return false;
bool continueExec = true;
int32_t code = mndTransPreFinish(pMnode, pTrans);
if (code == 0) {
pTrans->stage = TRN_STAGE_FINISHED;
mInfo("trans:%d, stage from pre-finish to finish", pTrans->id);
continueExec = true;
} else {
pTrans->failedTimes++;
mError("trans:%d, stage keep on pre-finish since %s, failedTimes:%d", pTrans->id, terrstr(), pTrans->failedTimes);
continueExec = false;
}
return continueExec;
}
static bool mndTransPerfromFinishedStage(SMnode *pMnode, STrans *pTrans) { static bool mndTransPerfromFinishedStage(SMnode *pMnode, STrans *pTrans) {
bool continueExec = false; bool continueExec = false;
...@@ -1545,6 +1581,14 @@ void mndTransExecute(SMnode *pMnode, STrans *pTrans, bool isLeader) { ...@@ -1545,6 +1581,14 @@ void mndTransExecute(SMnode *pMnode, STrans *pTrans, bool isLeader) {
case TRN_STAGE_UNDO_ACTION: case TRN_STAGE_UNDO_ACTION:
continueExec = mndTransPerformUndoActionStage(pMnode, pTrans); continueExec = mndTransPerformUndoActionStage(pMnode, pTrans);
break; break;
case TRN_STAGE_PRE_FINISH:
if (isLeader) {
continueExec = mndTransPerfromPreFinishedStage(pMnode, pTrans);
} else {
mInfo("trans:%d, can not pre-finish since not leader", pTrans->id);
continueExec = false;
}
break;
case TRN_STAGE_FINISHED: case TRN_STAGE_FINISHED:
continueExec = mndTransPerfromFinishedStage(pMnode, pTrans); continueExec = mndTransPerfromFinishedStage(pMnode, pTrans);
break; break;
......
system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1
system sh/deploy.sh -n dnode2 -i 2
system sh/deploy.sh -n dnode3 -i 3
system sh/deploy.sh -n dnode4 -i 4
system sh/cfg.sh -n dnode1 -c transPullupInterval -v 1
system sh/cfg.sh -n dnode2 -c transPullupInterval -v 1
system sh/cfg.sh -n dnode3 -c transPullupInterval -v 1
system sh/cfg.sh -n dnode4 -c transPullupInterval -v 1
system sh/exec.sh -n dnode1 -s start
system sh/exec.sh -n dnode2 -s start
system sh/exec.sh -n dnode3 -s start
system sh/exec.sh -n dnode4 -s start
sql connect
print =============== step1: create dnodes
sql create dnode $hostname port 7200
sql create dnode $hostname port 7300
sql create dnode $hostname port 7400
$x = 0
step1:
$x = $x + 1
sleep 1000
if $x == 10 then
return -1
endi
sql select * from information_schema.ins_dnodes -x step1
if $data(1)[4] != ready then
goto step1
endi
if $data(2)[4] != ready then
goto step1
endi
if $data(3)[4] != ready then
goto step1
endi
print =============== step2: create mnode 2 and 3
sql create mnode on dnode 2
sql create mnode on dnode 3
sql create database db vgroups 2
print =============== step3: kill dnode4
system sh/exec.sh -n dnode4 -s stop -x SIGKILL
sql use db
sql_error create table stb (ts timestamp, i int) tags (j int)
print =============== step4: create database
sql show transactions
if $rows != 1 then
return -1
endi
sleep 3000
system sh/exec.sh -n dnode4 -s start
$wt = 0
step4:
$wt = $wt + 1
sleep 1000
if $wt == 200 then
print ====> transaction already running
return -1
endi
sql show transactions
if $rows != 0 then
print wait 1 seconds to alter
goto step4
endi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册