From: Jim Starkey Date: March 19 2009 10:35pm Subject: Re: New Transaction State object (Was: Problems with record visibility and how it is computed) List-Archive: http://lists.mysql.com/falcon/625 Message-Id: <49C2C8AD.2020306@nimbusdb.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Olav Sandstaa wrote: > Hi Jim, > > Thanks for comments. I have gotten into the coding and have a running > prototype that fixes some of the issues we have seen. See some comment > inline: > > Jim Starkey wrote: >> I think TransactionState will also need: >> >> * Transaction id (for validation and sanity control) > > Agree but mainly for saving space by being able to remove it from the > RecordVersion object Yes! > >> * Transaction state > > Initially I agree with you but was also considering if the commitId > would be enough (commitId == 0 means active transaction, commitId != 0 > means committed - enough in most situations where we use the > TransactionState object). The main argument for not moving it from the > Transaction object to the TransactionState object is that this is used > many places in the Transaction code, also after the transaction has > committed. And that makes it a bit difficult to let the Transaction > object decrement the use count on the TransactionState object when the > transaction commits (and that is needed if we do not want to use > interlocked instructions for the use count). We can of course > duplicate the transaction state in both the Transaction object and the > TransactionState object (but I do not like that kind of duplication). Good enough. Non-zero commitId does the trick. > >> * syncPending (so it can be waited on) > > The main problem with including this is that it increases the size of > the TransactionState object from about 12 bytes to about 150 bytes (at > least with the currently enabled tracing code). How many of these can > "extreme testcases" produce? > > In the initial prototype I am working on I have moved the syncIsActive > (which is hopefully the same as you refer to as syncPending) to the > TransactionState object. > We are only waiting for active transactions so in all committed > TransactionState object this syncObject will never be used. In the > current implementation of Transaction::waitForTransaction() already > has a shared lock on the active transaction list. So I thing it will > be possible to ensure that we safely can use the syncObject also when > it is part of the Transaction object. The advantage of this is that we > do not need to ten-double the size of the TransactionState object. > > The drawback is that we can not easily get rid of neither the current > shared lock on the active transaction list or the active transaction > list (which I see you are aiming for). (and yes, I have an idea for > how to get rid of the currently used shared lock in > waitForTransaction()). The question is how one transaction waits for another. Does this work (or is there a simpler way): 1. Get a shared lock on active transaction list 2. Call addRef on transaction to wait for 3. Release shared lock on active transaction list 4. Wait on other transaction syncPending 5. Release syncPending 6. Call release on transaction waited on > >> >> This makes TransactionState the primary operational object and >> Transaction mostly for bookkeeping. I think this also eliminates the >> need for TransactionManager::activeTransactions. > > I agree but that should likely be a next step goal and not part of > this (which started as a bug fix for 41357). It occurred to me that we need the active transaction list to track down transaction that have updates to tables that the MySQL server wants to delete. I don't see anyway around it, at least not for now. I suggest we put this dream aside until less strenuous times. -- Jim Starkey President, NimbusDB, Inc. 978 526-1376