Skip to content

Document differences between memtx and vinyl transaction managers #2977

Open
@locker

Description

@locker

Related dev. issue(s): tarantool/tarantool#1944
Product: Tarantool
Since: always
Audience/target: users
Root document: https://www.tarantool.io/en/doc/latest/book/box/engines/memtx_vinyl_diff/
SME: @ locker @ alyapunov @ Mons

Details

There's a documentation page that enumerates differences between memtx and vinyl engines. We need to mention that starting from 2.6.1 memtx supports MVCC (aka yields in transactions) provided the box.cfg.memtx_use_mvcc_engine is set. Vinyl has always supported MVCC.

We also need to describe differences between memtx and vinyl implementations of MVCC. There's the only difference known so far: how tracking non-existing/deleted keys is implemented. Let's assume that one transaction reads a range of keys using select and yields. During the yield, another transaction deletes a key that doesn't exist in the index from the range using delete. The delete would abort the first transaction in vinyl, but wouldn't abort it in memtx. In particular, if a transaction reads a single key that doesn't exist in the index, then deleting the key in another transaction would abort it in vinyl, but not in memtx.

Example:

local net = require('net.box')

box.cfg{
    listen = 3301,
    log_level = 'warn',
    memtx_use_mvcc_engine = true,
}
box.once('init', function()
    box.schema.user.grant('guest', 'super')
    box.schema.create_space('memtx', {engine = 'memtx'})
    box.space.memtx:create_index('primary')
    box.schema.create_space('vinyl', {engine = 'vinyl'})
    box.space.vinyl:create_index('primary')
end)

box.space.memtx:truncate()
box.space.vinyl:truncate()

local conn = net.connect('localhost:3301')
local stream = conn:new_stream()

stream:begin()
stream.space.memtx:get{1}
stream.space.memtx:replace{2}
box.space.memtx:delete{1}
local ok, err = pcall(stream.commit, stream)
print(string.format("memtx: %s", ok and 'Success' or tostring(err)))

stream:begin()
stream.space.vinyl:get{1}
stream.space.vinyl:replace{2}
box.space.vinyl:delete{1}
local ok, err = pcall(stream.commit, stream)
print(string.format("vinyl: %s", ok and 'Success' or tostring(err)))

os.exit(0)

Output:

memtx: Success
vinyl: Transaction has been aborted by conflict

The issue is closely related to another memtx vs vinyl difference: in memtx delete returns the deleted tuple while in vinyl it doesn't, because it may not know if a tuple was actually deleted - it just writes a "delete" statement to the index without reading the key.

Definition of done

  • Added MVCC / yields in transactions entry to the memtx vs vinyl comparison table.
  • Described differences between memtx and vinyl transaction managers.

Planning checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions