From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH 2/4] vinyl: add tx to writers list in begin_statement engine callback Date: Mon, 4 Mar 2019 18:39:25 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: To: kostja@tarantool.org Cc: georgy@tarantool.org, tarantool-patches@freelists.org List-ID: Currently, we add a transaction to the list of writers when executing a DML request, i.e. in vy_tx_set. The problem is a transaction can yield on read before calling vy_tx_set, e.g. to check a uniqueness constraint, which opens a time window when a transaction is not yet on the list, but it will surely proceed to DML after it continues execution. If we need to abort writers in this time window, we'll miss it. To prevent this, let's add a transaction to the list of writers in vy_tx_begin_statement. Note, after this patch, when a transaction is aborted for DDL, it may have an empty write set - it happens if tx_manager_abort_writers is called between vy_tx_begin_statement and vy_tx_set. Hence we have to remove the corresponding assertion from tx_manager_abort_writers. Needed for #4016 --- src/box/vy_tx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c index 53c495d4..d216c73d 100644 --- a/src/box/vy_tx.c +++ b/src/box/vy_tx.c @@ -837,6 +837,8 @@ void * vy_tx_begin_statement(struct vy_tx *tx) { assert(tx->state == VINYL_TX_READY); + if (stailq_empty(&tx->log)) + rlist_add_entry(&tx->xm->writers, tx, in_writers); return stailq_last(&tx->log); } @@ -1057,8 +1059,6 @@ vy_tx_set_with_colmask(struct vy_tx *tx, struct vy_lsm *lsm, tx->write_set_version++; tx->write_size += tuple_size(stmt); vy_stmt_counter_acct_tuple(&lsm->stat.txw.count, stmt); - if (stailq_empty(&tx->log)) - rlist_add_entry(&tx->xm->writers, tx, in_writers); stailq_add_tail_entry(&tx->log, v, next_in_log); return 0; } @@ -1068,7 +1068,6 @@ tx_manager_abort_writers(struct tx_manager *xm, struct vy_lsm *lsm) { struct vy_tx *tx; rlist_foreach_entry(tx, &xm->writers, in_writers) { - assert(!vy_tx_is_ro(tx)); if (tx->state == VINYL_TX_READY && write_set_search_key(&tx->write_set, lsm, lsm->env->empty_key) != NULL) -- 2.11.0