20.07.2018 21:27, livius wrote:
  Not exactly so. When index key is not changed by UPDATE statement, engine 
doesn't
  add it into the index.

Ok, so it has not changed.

  Yes

tx1: insert record (r1) with index key (k1)
table contains one record version: r1-tx1
index contains one entry: (k2, r1)
tx1: commit

tx2: update r1 set key = k2
table contains two records versions: r1-tx2, r1-tx1
index contains two entries: (k1, r1), (k2, r1)
tx2: commit

garbage collector:
remove from disk r1-tx1,
build lists: staying (r1-tx2), going (r1-tx1)
going to cleanup indices
context switch...

table: r1-2
index: (k1, r1), (k2, r1)

tx3: update r1 set key = k1
table: r1-tx3, r1-tx2
index: (k1, r1), (k2, r1)
note, tx3 doesn't add index entry (k1, r1) as it is already present
tx3: commit

garbage collector:
...continue to cleanup indices
lists: staying (r1-tx2), going (r1-tx1)
keys: staying (k2), going (k1)
remove index key (k1, r1)

On disk
table: r1-tx3, r1-tx2
index: (k2, r1)

r1-tx3 contains key = k1, but index have no such entry

Very informative, thank you very much.
Above describe the problem, but how it was fixed after FB2 that we have now 
this issue?

  *Before* fb2 was released, this was changed to insert entry into index
despite of its presence. Scenario above actually run as:

tx1: insert record (r1) with index key (k1)
  table contains one record version: r1-tx1
  index contains one entry: (k2, r1)
tx1: commit

tx2: update r1 set key = k2
  table contains two records versions: r1-tx2, r1-tx1
  index contains two entries: (k1, r1), (k2, r1)
tx2: commit

garbage collector:
  remove from disk r1-tx1,
  build lists: staying (r1-tx2), going (r1-tx1)
  going to cleanup indices
  context switch...

  table: r1-2
  index: (k1, r1), (k2, r1)

tx3: update r1 set key = k1
  table: r1-tx3, r1-tx2
  index: (k1, r1), (k1, r1), (k2, r1)
note, tx3 *adds* index entry (k1, r1)
tx3: commit

garbage collector:
  ...continue to cleanup indices
  lists: staying (r1-tx2), going (r1-tx1)
  keys: staying (k2), going (k1)
  remove index key (k1, r1)

On disk
  table: r1-tx3, r1-tx2
  index: (k1, r1), (k2, r1)

Now index contains all necessary entries.


But sometime it could contain non-removable, excessive entries:

tx1: insert record (r1) with index key (k1)
  table contains one record version: r1-tx1
  index contains one entry: (k2, r1)
tx1: commit

tx2: update r1 set key = k2
  table contains two records versions: r1-tx2, r1-tx1
  index contains two entries: (k1, r1), (k2, r1)

tx2: update r1 set key = k1
  table contains tree records versions: r1(k1)-tx2, r1(k2)-tx2, r1(k1)-tx1
  index contains tree entries: (k1, r1), (k1, r1), (k2, r1)

Then engine immediately removes first record version, created by tx2
  remove from disk r1(k2)-tx1
  build lists: staying r1(k1)-tx2, r1(k1)-tx1, going r1(k2)-tx2
  keys: staying (k1, k1), going (k2)
  remove index key (k2, r1)

On disk
  table: r1(k1)-tx2, r1(k1)-tx1
  index: (k1, r1), (k1, r1)

tx2: commit

garbage collector:
  remove from disk: r1(k1)-tx1
  lists: staying (r1-tx2), going (r1-tx1)
  keys: staying (k1), going (k1)
  no index key is removed

On disk
  table: r1-tx2
  index: (k1, r1), (k1, r1)

Now we have excess index entry on disk.

Hope it is clear,
Vlad

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to