List:Falcon Storage Engine« Previous MessageNext Message »
From:Kevin Lewis Date:December 5 2008 5:03am
Subject:Re: Bug 41194
View as plain text  

If there is no index on i_im_id, each of the update statements will read
every record int the table with a record lock (or an implicit
select-for-update) and return each record back to the MySQL server to do
the select.  The the server updates only the selected records, but the
others are still locked until the end of the transaction.

This is an important optimization technique.  Falcon does not use range
locks.  It creates a temporary 'lock record' as the newest record
version.  This prevents other transactions from changing that record
while it is there.


Hu, Xuekun wrote:
> Hi, Ann & Kevin
> Thanks for replying. However I can't explain the below example:
> I used dbt2 dataset. First I used gdb attached to mysqld to break
> "Transaction::waitForTransaction()".
> Second I used two transactions to do each of below 
> 	mysql -e "update dbt2.item set i_name='adf' where i_im_id=1;" &
> 	mysql -e "update dbt2.item set i_name='gfg' where i_im_id=2;" &
> Then I found mysqld is stopped at Transaction::waitForTransaction which means the two
> transactions have update conflict. I can't explain how the two transactions are thought as
> a potential update conflict. And actually I can't find an example which two transactions
> are updating one table which will not be blocked. 
> Sorry for my cavil. :-) Your comments are appreciated. 
> Thx, Xuekun
> -----Original Message-----
> From: Ann.Harrison@stripped [mailto:Ann.Harrison@stripped] On Behalf Of Ann W.
> Harrison
> Sent: 2008年12月5日 0:10
> To: Hu, Xuekun
> Cc: Kevin Lewis; Kevin Lewis; Jim Starkey; FalconDev; Yu, Zhidong; Fang, Xiang; Duan,
> Jiangang
> Subject: Re: Bug 41194
> Hi Xuekun,
>> I happened to read Transaction::commit() code, since I  
>> found most contention are due to transaction commit,
>> some transactions are waiting at waitForTransaction
>> due to other transaction::syncIsActive is locked.
> That situation occurs when there is a potential update
> conflict between two transactions.  While it is active,
> a transaction keeps its syncIsActive locked exclusively.
> Suppose that transaction A updates a record.  When
> transaction B starts, transaction A is still active (on
> the active list).  B attempts to update the same record,
> realizes that A was active when B started, so there's a
> possible conflict.  B queues a lock on A's syncIsActive
> and waits for A to complete and release its lock.  When
> B gets a shared lock on A's syncIsActive, it checks A's
> final state, and if A has committed, B gets an error on
> it's update.  If A rolled back, B's update succeeds.
> A similar series of events occur when B attempts to store
> a record that has a unique index (primary or unique
> constraint) and A has stored a record with the same value.
> B waits for A to complete and then gets an error if A
> committed or proceeds if A rolled back.
>> So I wonder does this order violate MVCC semantics? 
>>   1) Durability - write committed record to serial log.
>>   2) Transaction::state = committed
>>   3) Transaction::syncIsActive.unlock()
>>   4) synchronously move trans from Active to committed lists
>> This order may decrease the waiting time of waiting transaction. 
> I don't think it breaks transaction semantics, but I worry
> about it's effect on internal Falcon logic.
> Writing the the serial log has to happen before any other
> transaction can see the committing transaction's changes.
> That's by far the most expensive step in the commit - there's
> a physical write involved - the serial log must be flushed.
> Unless the serial log is on a solid state device or RAM disk,
> the flush is two orders of magnitude more expensive than
> the other three steps combined.
> Certainly, you shouldn't unlock syncIsActive before setting
> the state to committed; step 2 has to occur before step 3.
> I'd prefer to see step 4 before steps 2 and 3, even if it
> increases the time that other transactions have to wait.
> First, there's the issue of having a transaction in the
> active list with its state property set to committed, but
> without a valid commitId.
> Second, if the waiting transactions are running in
> repeatable read mode, they're going to get errors on
> their current operations, that require that they
> end their current transaction before retrying the
> operation.
>> Another thinking is how you decide two transactions have  
>> dependency. I only found if two transactions are updating  
>> the same table, then one transaction will wait for the  
>> other transaction committed. So seems like  
>> Transaction::syncIsActive is at table level lock, which  
>> seems not very efficient. 
> It's not a table level lock - it's a row (record) level
> lock.
> "Dependency" is a confusing word here - it had been used
> to indicate that a transaction needs to read the state of
> records before some other transaction changed them, and
> limited the scope of scavenging old record versions.
> I think you mean, how does a transaction get in a state
> where it is waiting for a lock on some other transaction's
> syncIsActive.  As I explained above, that happens when
> the two transactions have tried to update the same record
> or insert the same value into a unique index.
> It's not a table level lock - it's a row (record) level
> lock.
> Best regards,
> Ann
Bug 41194Ann W. Harrison3 Dec
  • Re: Bug 41194Kevin Lewis3 Dec
    • Re: Bug 41194Ann W. Harrison3 Dec
      • RE: Bug 41194Xuekun Hu4 Dec
  • Re: Bug 41194Kevin Lewis4 Dec
    • RE: Bug 41194Xuekun Hu4 Dec
  • Re: Bug 41194Ann W. Harrison4 Dec
    • RE: Bug 41194Xuekun Hu5 Dec
  • Re: Bug 41194Kevin Lewis4 Dec
  • Re: Bug 41194Kevin Lewis5 Dec
    • RE: Bug 41194Xuekun Hu5 Dec