Mike Matrigali wrote:
null pointer is a bug, please report as a separate JIRA,not sure
what is going on.  Note that while it is convenient for testing
purposes to use the SYSCS_UTIL.SYSCS_INPLACE_COMPRESS_TABLE
to cause the purging, purging of rows can happen at any time
after a delete has been committed.  The timing depends on a
number of factors and the timing may change in the future - so
one should assume that as soon as a row is deleted and committed
it may be purged.

Andreas Korneliussen wrote:

Mike Matrigali wrote:

From the store point of view, 3 things can happen to
RowLocations in heap tables:
1) It can be deleted (requires at least TABLE IX, ROW X locking)
       o internal to store it is just marked deleted
       o external to store requests for any operation on
         this row will fail.  Note that your cursor can
         experience this no matter what locking you do, as
         it is always possible for another statement in your
         transaction to do the delete.
2) It can be purged (requires at least TABLE IX, ROW X locking)
       o all physical evidence of the row is removed from table,
         both internal and external operations on this row will
         fail.  Only committed deleted rows are purged.
         Note this will never happen if you have some
         sort of lock on the row as the requested X lock is
         always requested in a system only transaction.
       o the actual RowLocation will not be reused while
         at least some sort of table level intent lock is held.
3) It can be reused (requires a table level X lock)
       o basically as part of a compress all rows can be shuffled
         in any way.  A former RowLocation can now point to
         a completely different row.

So as you point out, your implementation can have serious problems
with cursors held over commit.  This is why in current usage of
cursors over commit the only safe thing to do is to ask for the
next row location and use it.

Please make sure to consider the delete/purge cases also.  One case
that often causes problems is a transaction deleting a row that is
locked by it's own cursor from another statement in the same connection.

Yes, we need to consider those cases.

It seems that the store is capable of graciously handle that the row get deleted (i.e by its own transaction). If the transaction later tries to update the deleted row using the resultset, the store call will return false indicating that the row was not updated. The deleted row will not be purged as long as the transaction is open.

However in read-committed/read-uncommitted mode, a row read by the cursor, can be deleted by another transaction, and then purged. It seems that the store does not handle an update of a deleted+purged record.

On our prototype impl., I get a get a NullPointerException from the store in this case. It comes in GenericConglomerateController.replace(..)).

I would think there are multiple ways of adressing this issue:

1 We could make the store graciously handle the situation if the RowLocation points to a deleted+purged row, by returning false if the RowLocation is invalid, (and from the caller we can give an exception)

It seems like the ConglomerateController.replace() function should throw
an exception (other than null pointer) if it is called with a non-existent RowLocation, but I could be convinced returning false is ok. The problem I have is that store really has no way to tell the difference between a BAD RowLocation input and one which was purged.


Yes, maybe the store should throw an exception if the RowLocation is invalid. Seen from the user perspective, I think the update should fail the same way whether the row has been deleted+purged or only deleted Currently the function returns false if the row has been deleted.

I ran a check on all places in the code tree that the ConglomerateCongtroller.replace(..) method is called. I found that the return value is silently ignored all places, except for in the store unit-tests.

This means that an updateRow() on a deleted record, would simply return silently (using the optimistic concurrency approach). After the transaction has committed, the row would remain deleted.

I will file a JIRA for the NullPointerException case.

--Andreas




Reply via email to