Tarantool development patches archive
 help / color / mirror / Atom feed
From: Konstantin Osipov <kostja@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Georgy Kirichenko <georgy@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v3 05/14] txn: get rid of autocommit from a txn structure
Date: Sun, 16 Jun 2019 19:20:29 +0300	[thread overview]
Message-ID: <20190616162029.GB28257@atlas> (raw)
In-Reply-To: <20190613141102.dw4odqbse6cwawc4@esperanza>

* Vladimir Davydov <vdavydov.dev@gmail.com> [19/06/13 17:18]:
> On Sun, Jun 09, 2019 at 11:44:34PM +0300, Georgy Kirichenko wrote:
> > Move transaction auto start and auto commit behavior to the box level.
> > From now a transaction won't start and commit automatically without
> > txn_begin/txn_commit invocations. This is a part of a bigger transaction
> > refactoring in order to implement detachable transactions and a parallel
> > applier.
> 
> TBO I don't understand why you need to move autocommit logic out of txn.
> The applier code already calls txn_begin/txn_commit explicitly and AFAIU
> this is the only place you need to care about. The code looks less
> readable and more bulky after this change IMHO. Let's discuss f2f.

We duplicate autocommit logic on box and SQL level, this is
confusing. This is why we decided to get rid of it altogether in
box. I think when
the refactoring is finished the box code won't look that ugly,
especially after your suggestions.

> fiber_gc() must be called after txn_commit() while txn_rollback() calls
> it by itself. This is a mess.

It is temporary, the patch tries to do equivalent transformations
of the source code, the issue is addressed by a subsequent patch.

> why we need to call this function at all now, when we have txn->region
> which is used to allocate all txn stuff. AFAIU fiber->gc is only used
> for allocating temporary objects, in which case the caller is supposed
> to clean up by himself (using region_truncate). That said, I don't think
> we need to call fiber_gc() after txn_commit() at all.

Indeed, when most of transaction memory is allocated on txn gc,
txn_commit() will free that memory automatically.

> There's one exception though - it's vdbe_add_new_autoinc_id, which
> stores autogenerated ids on fiber->gc and doesn't delete them until
> the corresponding SQL request is complete (this is why all this mess
> with fiber_gc() started AFAIR). However, I think we could and should
> use a mempool for such allocations.
> 
> I think that before pushing this patch, we should clean up fiber_gc()
> usage, otherwise it's really easy to loose track where we must and where
> we mustn't call fiber_gc() now. Actually, I think we should do that
> irrespective of whether we commit this patch or not.

No, I disagree, that would be unnecessary work, we just need to
finish the patch set and push it.

> > @@ -403,8 +418,16 @@ applier_join(struct applier *applier)
> >  		applier->last_row_time = ev_monotonic_now(loop());
> >  		if (iproto_type_is_dml(row.type)) {
> >  			vclock_follow_xrow(&replicaset.vclock, &row);
> > -			if (apply_row(&row) != 0)
> > +			struct txn *txn = txn_begin();
> > +			if (txn == NULL)
> > +				diag_raise();
> > +			if (apply_row(&row) != 0) {
> > +				txn_rollback();
> > +				diag_raise();
> > +			}
> > +			if (txn_commit(txn) != 0)
> >  				diag_raise();
> > +			fiber_gc();
> 
> I'd wrap this into a helper function (apply_final_join_row).

Ok, why not.

> > diff --git a/src/box/box.cc b/src/box/box.cc
> > index 57419ee01..7f23716e5 100644
> > --- a/src/box/box.cc
> > +++ b/src/box/box.cc
> > @@ -169,34 +169,62 @@ int
> >  box_process_rw(struct request *request, struct space *space,
> >  	       struct tuple **result)
> >  {
> > +	struct tuple *tuple = NULL;
> > +	struct txn *txn = in_txn();
> > +	bool is_autocommit = txn == NULL;
> > +	if (is_autocommit && (txn = txn_begin()) == NULL)
> > +		return -1;
> >  	assert(iproto_type_is_dml(request->type));
> >  	rmean_collect(rmean_box, request->type, 1);
> >  	if (access_check_space(space, PRIV_W) != 0)
> > -		return -1;
> > -	struct txn *txn = txn_begin_stmt(space);
> > -	if (txn == NULL)
> > -		return -1;
> > -	struct tuple *tuple;
> > +		goto fail;
> > +	if (txn_begin_stmt(txn, space) == NULL)
> > +		goto fail;
> >  	if (space_execute_dml(space, txn, request, &tuple) != 0) {
> > -		txn_rollback_stmt();
> > -		return -1;
> > +		txn_rollback_stmt(txn);
> > +		goto fail;
> > +	}
> > +	if (result != NULL)
> > +		*result = tuple;
> > +
> > +	if (result == NULL || tuple == NULL) {
> > +		if (txn_commit_stmt(txn, request) != 0)
> > +			goto fail;
> > +		if (is_autocommit) {
> > +			if (txn_commit(txn) != 0)
> > +				return -1;
> > +			fiber_gc();
> > +		}
> > +		return 0;
> >  	}
> > -	if (result == NULL)
> > -		return txn_commit_stmt(txn, request);
> > -	*result = tuple;
> > -	if (tuple == NULL)
> > -		return txn_commit_stmt(txn, request);
> >  	/*
> >  	 * Pin the tuple locally before the commit,
> >  	 * otherwise it may go away during yield in
> >  	 * when WAL is written in autocommit mode.
> >  	 */
> >  	tuple_ref(tuple);
> > -	int rc = txn_commit_stmt(txn, request);
> > -	if (rc == 0)
> > -		tuple_bless(tuple);
> > +
> > +	if (txn_commit_stmt(txn, request)) {
> > +		/* Unref tuple and rollback if autocommit. */
> > +		tuple_unref(tuple);
> > +		goto fail;
> > +	}
> > +	if (is_autocommit) {
> > +		if (txn_commit(txn) != 0) {
> > +			/* Unref tuple and exit. */
> > +			tuple_unref(tuple);
> > +			return -1;
> > +		}
> > +	        fiber_gc();
> > +	}
> > +	tuple_bless(tuple);
> 
> This looks like a lot of copy-n-paste. Please think on how to get rid of
> code duplication.

This is already after my changes are applied, I think the place
needs to be revisited when txn alloc is in, not in the middle of a
patch stack.


> > @@ -299,10 +327,20 @@ apply_wal_row(struct xstream *stream, struct xrow_header *row)
> >  	xrow_decode_dml_xc(row, &request, dml_request_key_map(row->type));
> >  	if (request.type != IPROTO_NOP) {
> >  		struct space *space = space_cache_find_xc(request.space_id);
> > +		struct txn *txn = txn_begin();
> > +		if (txn == NULL) {
> > +			say_error("error applying row: %s", request_str(&request));
> > +			diag_raise();
> > +		}
> 
> Why? box_process_rw can handle autocommit statements.

Uhm, good point, Let's try to not add transaction management here. 

> 
> >  		if (box_process_rw(&request, space, NULL) != 0) {
> >  			say_error("error applying row: %s", request_str(&request));
> > +			txn_rollback();
> >  			diag_raise();
> >  		}
> > +		if (txn_commit(txn) != 0) {
> > +			diag_raise();
> > +		}
> > +		fiber_gc();
> >  	}
> >  	struct wal_stream *xstream =
> >  		container_of(stream, struct wal_stream, base);
> > @@ -1313,9 +1351,17 @@ box_sequence_reset(uint32_t seq_id)
> >  static inline void
> >  box_register_replica(uint32_t id, const struct tt_uuid *uuid)
> >  {
> > +	struct txn *txn = txn_begin();
> > +	if (txn == NULL)
> > +		diag_raise();
> >  	if (boxk(IPROTO_INSERT, BOX_CLUSTER_ID, "[%u%s]",
> 
> Again, boxk call box_process_rw, which handles autocommit. No need to
> call txn_begin/txn_commit here explicitly.

Agree.

> > @@ -1636,10 +1682,18 @@ box_set_replicaset_uuid(const struct tt_uuid *replicaset_uuid)
> >  		uu = *replicaset_uuid;
> >  	else
> >  		tt_uuid_create(&uu);
> > +	struct txn *txn = txn_begin();
> > +	if (txn == NULL)
> > +		diag_raise();
> >  	/* Save replica set UUID in _schema */
> >  	if (boxk(IPROTO_INSERT, BOX_SCHEMA_ID, "[%s%s]", "cluster",
> 
> Same here.

Agree.

> > diff --git a/src/box/index.cc b/src/box/index.cc
> > index 4a444e5d0..7f26c9bc2 100644
> > --- a/src/box/index.cc
> > +++ b/src/box/index.cc
> > @@ -274,7 +274,7 @@ box_index_min(uint32_t space_id, uint32_t index_id, const char *key,
> >  	if (txn_begin_ro_stmt(space, &txn) != 0)
> >  		return -1;
> >  	if (index_min(index, key, part_count, result) != 0) {
> > -		txn_rollback_stmt();
> > +		txn_rollback_stmt(txn);
> 
> In general I like that txn_rollback_stmt and txn_rollback now take txn.
> This makes the API more symmetric. Probably, worth doing in a separate
> patch, even if we realize we don't need this one. As a matter of fact,
> doing this in a separate patch would make review easier. I'd appreciate
> if you could split this patch.

Agree.

> > diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
> > index f4312484a..149215b87 100644
> > --- a/src/box/memtx_engine.c
> > +++ b/src/box/memtx_engine.c
> > @@ -272,16 +272,22 @@ memtx_engine_recover_snapshot_row(struct memtx_engine *memtx,
> >  		diag_set(ClientError, ER_CROSS_ENGINE_TRANSACTION);
> >  		return -1;
> >  	}
> > +	struct txn *txn = txn_begin();
> > +	if (txn == NULL)
> > +		return -1;
> >  	/* no access checks here - applier always works with admin privs */
> > -	if (space_apply_initial_join_row(space, &request) != 0)
> > +	if (space_apply_initial_join_row(space, &request) != 0) {
> > +		txn_rollback();
> >  		return -1;
> > +	}
> > +	int rc = txn_commit(txn);
> 
> This is the second place where you surround apply_initial_join_row with
> txn_begin/txn_commit. May be, worth doing it in the callback itself?
> Note, we only need this in case of memtx - vinyl doesn't create a txn
> object for initial recover or join.

Agree.

> 
> > diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c
> > index 1d209033c..1e630783b 100644
> > --- a/src/box/memtx_space.c
> > +++ b/src/box/memtx_space.c
> > @@ -310,10 +310,10 @@ memtx_space_apply_initial_join_row(struct space *space, struct request *request)
> >  		return -1;
> >  	}
> >  	request->header->replica_id = 0;
> > -	struct txn *txn = txn_begin_stmt(space);
> > -	if (txn == NULL)
> > +	struct txn *txn = in_txn();
> > +	struct txn_stmt *stmt = txn_begin_stmt(txn, space);
> > +	if (stmt == NULL)
> >  		return -1;
> > -	struct txn_stmt *stmt = txn_current_stmt(txn);
> 
> AFAICS this is the only place where you use txn_stmt returned by
> txn_begin_stmt() - in other places you simply check if it's NULL (which
> indicates an error). Why did you decide to make txn_begin_stmt() return
> txn_stmt rather than an error code? The API looks lopsided now:
> 
>   txn_begin() => txn
>   txn_begin_stmt(txn, request) => txn_stmt
>   txn_commit_stmt(txn) => int
>   txn_commit(txn) => int
> 
> Let's please make txn_begin_stmt return int and use txn_current_stmt
> here to get txn_stmt, as we used to. This shouldn't affect performance
> while the code would look neater this way.

Agree.

> 
> > diff --git a/src/box/txn.c b/src/box/txn.c
> > index 1d8271e51..21f34e526 100644
> > --- a/src/box/txn.c
> > +++ b/src/box/txn.c
> > @@ -441,14 +428,11 @@ fail:
> >  }
> >  
> >  void
> > -txn_rollback_stmt()
> > +txn_rollback_stmt(struct txn *txn)
> >  {
> > -	struct txn *txn = in_txn();
> >  	if (txn == NULL || txn->in_sub_stmt == 0)
> >  		return;
> 
> Hmm, how's that even possible now?

Nothing changed here, why would this become impossible?

-- 
Konstantin Osipov, Moscow, Russia

  reply	other threads:[~2019-06-17  5:16 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-09 20:44 [tarantool-patches] [PATCH v3 00/14] Parallel applier Georgy Kirichenko
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 01/14] txn: Fire a trigger after a transaction finalization Georgy Kirichenko
2019-06-09 21:59   ` [tarantool-patches] " Konstantin Osipov
2019-06-11 11:42   ` [tarantool-patches] " Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 02/14] ddl: synchronize privileges cache with actual data state Georgy Kirichenko
2019-06-11 13:13   ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 03/14] txn: transaction memory allocation Georgy Kirichenko
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 04/14] ddl: place alter structures onto a txn memory region Georgy Kirichenko
2019-06-11 14:14   ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 05/14] txn: get rid of autocommit from a txn structure Georgy Kirichenko
2019-06-13 14:11   ` Vladimir Davydov
2019-06-16 16:20     ` Konstantin Osipov [this message]
2019-06-16 16:14   ` [tarantool-patches] " Konstantin Osipov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 06/14] txn: get rid of fiber_gc from txn_rollback Georgy Kirichenko
2019-06-13 14:12   ` Vladimir Davydov
2019-06-13 19:28     ` Георгий Кириченко
2019-06-14  9:21       ` Vladimir Davydov
2019-06-16 16:38   ` [tarantool-patches] " Konstantin Osipov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 07/14] wal: remove fiber from a journal_entry structure Georgy Kirichenko
2019-06-13 14:17   ` Vladimir Davydov
2019-06-13 19:33     ` Георгий Кириченко
2019-06-14  8:05       ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 08/14] wal: enable asyncronous wal writes Georgy Kirichenko
2019-06-13 14:21   ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 09/14] wal: a dedicated wal scheduling fiber Georgy Kirichenko
2019-06-13 14:24   ` Vladimir Davydov
2019-06-13 19:36     ` Георгий Кириченко
2019-06-14  9:20       ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 10/14] core: latch_unlock_external routine Georgy Kirichenko
2019-06-13 14:27   ` Vladimir Davydov
2019-06-13 19:38     ` Георгий Кириченко
2019-06-14  8:10       ` Vladimir Davydov
2019-06-14  9:18         ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 11/14] txn: introduce asynchronous txn commit Georgy Kirichenko
2019-06-13 14:34   ` Vladimir Davydov
2019-06-13 19:45     ` Георгий Кириченко
2019-06-14  7:58       ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 12/14] txn: handle fiber stop event at transaction level Georgy Kirichenko
2019-06-13 14:36   ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 13/14] applier: apply transaction in parallel Georgy Kirichenko
2019-06-13 15:17   ` Vladimir Davydov
2019-06-09 20:44 ` [tarantool-patches] [PATCH v3 14/14] test: fix flaky test Georgy Kirichenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190616162029.GB28257@atlas \
    --to=kostja@tarantool.org \
    --cc=georgy@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v3 05/14] txn: get rid of autocommit from a txn structure' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox