You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@directory.apache.org by Emmanuel Lécharny <el...@gmail.com> on 2018/09/15 03:47:55 UTC

Transaction implementation

Hi guys,

I had little time this week, but my last insomnia helped me moving
forward :-)

The transaction support in the server is now taking shape. I as able to
run a test where I inject 100 000 entries within one single transaction
(yes, it's a bit dumb, but...) and it shows that it's around 5x faster
than if we add those entries with no transaction being started (534
add/s vs 114 add/s). This is for JDBM partition.

The benefit is that if you know beforehand that you gonna have many
updates to inject, then you can gather them and get a good speed up.

I still have to implement the commit/rollback, which is not that complex.

The only drawback is that we will need to cut a new LDA¨P API release,
because most of the fixes to get it work were relative to some bad
implementation of the extended request.
-- 
Emmanuel Lecharny

Symas.com
directory.apache.org


Re: Update: Transaction implementation

Posted by Emmanuel Lécharny <el...@gmail.com>.

Le 20/09/2018 à 14:57, Howard Chu a écrit :
> Emmanuel Lécharny wrote:
>>
>>
>> Le 20/09/2018 à 14:18, Howard Chu a écrit :
>>> Emmanuel Lécharny wrote:
>>>> Hi !
>>>> Now, there is more work to do :
>>>> o rollback hasn't been tested yet
>>>> o we need to forbid concurrent writes while a transaction is being
>>>> executed - which means that a transaction is seen as one single giant
>>>> write - with the consequence that a rogue client starting a transaction
>>>> but never finishing it will potentially lock the server.
>>>> o a mechanism to protect the server against such rogues client has to be
>>>> implemented (could be a limitation in the number of update per
>>>> transaction and/or a time limit for a transaction).
>>>
>>> In OpenLDAP we simply queue the incoming ops until the Commit is received,
>>> then execute them all at once. And yes, there's a limit on the number of
>>> ops allowed in a txn.
>>
>>
>> In ApacheDS, that would not save a lot of CPU/time, as the work is done
>> when updates are injected in the in-memory pages and flushed on disk.
>> Stacking them and injecting them in one shot will not save anything.
> 
> This isn't meant as a performance optimization, it's about error handling.
> It's to prevent transactions from keeping the DB locked for long times while
> the client is sending operations. This way we only start writing a txn to a DB
> when we know all of its ops are already present and we don't need to
> worry about the client timing out in the middle.

Understood. Typically useful if the client sends a endTransaction with
the commit flag set to false. Sounds like a smart way to deal with this
use case. Thanks for the trick !

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org


Re: Update: Transaction implementation

Posted by Howard Chu <hy...@symas.com>.
Emmanuel Lécharny wrote:
> 
> 
> Le 20/09/2018 à 14:18, Howard Chu a écrit :
>> Emmanuel Lécharny wrote:
>>> Hi !
>>> Now, there is more work to do :
>>> o rollback hasn't been tested yet
>>> o we need to forbid concurrent writes while a transaction is being
>>> executed - which means that a transaction is seen as one single giant
>>> write - with the consequence that a rogue client starting a transaction
>>> but never finishing it will potentially lock the server.
>>> o a mechanism to protect the server against such rogues client has to be
>>> implemented (could be a limitation in the number of update per
>>> transaction and/or a time limit for a transaction).
>>
>> In OpenLDAP we simply queue the incoming ops until the Commit is received,
>> then execute them all at once. And yes, there's a limit on the number of
>> ops allowed in a txn.
> 
> 
> In ApacheDS, that would not save a lot of CPU/time, as the work is done
> when updates are injected in the in-memory pages and flushed on disk.
> Stacking them and injecting them in one shot will not save anything.

This isn't meant as a performance optimization, it's about error handling.
It's to prevent transactions from keeping the DB locked for long times while
the client is sending operations. This way we only start writing a txn to a DB
when we know all of its ops are already present and we don't need to
worry about the client timing out in the middle.

-- 
  -- Howard Chu
  CTO, Symas Corp.           http://www.symas.com
  Director, Highland Sun     http://highlandsun.com/hyc/
  Chief Architect, OpenLDAP  http://www.openldap.org/project/

Re: Update: Transaction implementation

Posted by Emmanuel Lécharny <el...@gmail.com>.

Le 20/09/2018 à 14:18, Howard Chu a écrit :
> Emmanuel Lécharny wrote:
>> Hi !
>> Now, there is more work to do :
>> o rollback hasn't been tested yet
>> o we need to forbid concurrent writes while a transaction is being
>> executed - which means that a transaction is seen as one single giant
>> write - with the consequence that a rogue client starting a transaction
>> but never finishing it will potentially lock the server.
>> o a mechanism to protect the server against such rogues client has to be
>> implemented (could be a limitation in the number of update per
>> transaction and/or a time limit for a transaction).
> 
> In OpenLDAP we simply queue the incoming ops until the Commit is received,
> then execute them all at once. And yes, there's a limit on the number of
> ops allowed in a txn.


In ApacheDS, that would not save a lot of CPU/time, as the work is done
when updates are injected in the in-memory pages and flushed on disk.
Stacking them and injecting them in one shot will not save anything.

Now, it may allow some other updates to be executed before the
endTransaction is committed, but the risk is that the bigger transaction
is rollbacked due to some errors caused by the updates received during
the txn. This is a choice we could refine later, as the wall are not yet
painted ;-)

> 
>> Note that while a
>> transaction is being conducted, nothing is flushed on disk.
>> o more tests are to be conducted (do we see entries being updated during
>> a transaction if we do a search aside the transaction ?)
> 
> The RFC doesn't require searches to honor transactions. The spec really
> just allows you to perform multiple write ops as a single atomic operation.

With JDBM, I don't know how well searches would be executed while a
transaction is ongoing. With Mavibot, it's totally safe, as with MDB, as
a search will simply use teh latest committed version, and teh
transaction creates a new revision. But you already know that, just
mentionning for clarity.

> 
>> o controls are not returned back atm, as they should
>>
>> Otherwise, I have met some issues in other parts of the server whild
>> implementing transactions :
>>
>> o for most of the operations, controls aren't sent back to the client
>> (except for the Bind Operation)
>> o We should write a <Operation>Decorator instead of a request/response
>> implementation, to avoid a call to a method that is a big switch doing
>> the exact same thing. This is a bit cleaner.
>>
>> Also note that if the partition does not support transactions, then the
>> transaction requests are simply ignored.
>>
>> I will commit the code when the previous listed points have been
>> fixed/implemented.
>>
>> I do think we should leverage this extension when injecting a huge
>> number of entries into the server, like when using Studio to import a
>> LDIF file. I would suggest to gather updates in block of 100 to get a
>> good boost (x3) without blocking the writes for other clients for too
>> long (300ms).
> 
> Yes, in OpenLDAP 2.5 we can use txns to batch replication updates, also for
> performance reasons.

I'm not absolutely sure it's a good idea ('not sure', aka 'I have not
yet a solid opinion') : we generally don't know how many updates we are
going to have to replicate, so arbitrarily decide that updates are going
to be sent by batches of N updates is likely to be problematic (but I
may be wrong). But something similar to the Nagle algorithm applied to
replication could certainly work, that's for sure. At worse, in this
case, you may differ replication by a few seconds to take the chance to
speedup the average replication. This is worthfull when you know that
some periodic updates are scheduled (like daily updates). This is a
frequent use case in many companies.

Ideally speaking, this should be driven by a control...

Thanks for yout insights Howard, interesting, as always !

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org


Re: Update: Transaction implementation

Posted by Howard Chu <hy...@symas.com>.
Emmanuel Lécharny wrote:
> Hi !
> 
> A few insomnias later... ;-)
> 
> So I'm almost done with transaction implementation in the server (with a
> LOT of fixes on the client side too...)
> 
> I have run some perf tests where I inject a number of entries, with a
> different set of transaction size.  Here are the results :
> 
> Nb updates/transaction   Nb add/s
> 
> 0                        116
> 1                        108
> 2                        158
> 5                        208
> 10                       243
> 20                       270
> 50                       285
> 100                      303
> 200                      322
> 500                      357
> 1000                     400
> 
> As we can see, we are slightly slower when we send a transaction
> operation for every add, compared to no transaction being sent (which is
> kind of making sense, as we send 3 operations instead of one -
> startTxn/add/endTxn vs add -).
> 
> When we gather 2 adds into one single transaction, we get an almost 50%
> speed improvement, which tops around a 4x improvement when we gather
> 1000 adds within one single transaction.
> 
> Note that the test I run do commit every N addition, and I'm injecting
> 10000 entries total (numbers aren't changing significantly if I inject
> 100 000 entries, it's just that a run would take many minutes instead of
> 20s to 3mins).
> 
> So it does the job, and it improves performance.

Congratulations!

> Now, there is more work to do :
> o rollback hasn't been tested yet
> o we need to forbid concurrent writes while a transaction is being
> executed - which means that a transaction is seen as one single giant
> write - with the consequence that a rogue client starting a transaction
> but never finishing it will potentially lock the server.
> o a mechanism to protect the server against such rogues client has to be
> implemented (could be a limitation in the number of update per
> transaction and/or a time limit for a transaction).

In OpenLDAP we simply queue the incoming ops until the Commit is received,
then execute them all at once. And yes, there's a limit on the number of
ops allowed in a txn.

> Note that while a
> transaction is being conducted, nothing is flushed on disk.
> o more tests are to be conducted (do we see entries being updated during
> a transaction if we do a search aside the transaction ?)

The RFC doesn't require searches to honor transactions. The spec really
just allows you to perform multiple write ops as a single atomic operation.

> o controls are not returned back atm, as they should
> 
> Otherwise, I have met some issues in other parts of the server whild
> implementing transactions :
> 
> o for most of the operations, controls aren't sent back to the client
> (except for the Bind Operation)
> o We should write a <Operation>Decorator instead of a request/response
> implementation, to avoid a call to a method that is a big switch doing
> the exact same thing. This is a bit cleaner.
> 
> Also note that if the partition does not support transactions, then the
> transaction requests are simply ignored.
> 
> I will commit the code when the previous listed points have been
> fixed/implemented.
> 
> I do think we should leverage this extension when injecting a huge
> number of entries into the server, like when using Studio to import a
> LDIF file. I would suggest to gather updates in block of 100 to get a
> good boost (x3) without blocking the writes for other clients for too
> long (300ms).

Yes, in OpenLDAP 2.5 we can use txns to batch replication updates, also for
performance reasons.

-- 
  -- Howard Chu
  CTO, Symas Corp.           http://www.symas.com
  Director, Highland Sun     http://highlandsun.com/hyc/
  Chief Architect, OpenLDAP  http://www.openldap.org/project/

Update: Transaction implementation

Posted by Emmanuel Lécharny <el...@gmail.com>.
Hi !

A few insomnias later... ;-)

So I'm almost done with transaction implementation in the server (with a
LOT of fixes on the client side too...)

I have run some perf tests where I inject a number of entries, with a
different set of transaction size.  Here are the results :

Nb updates/transaction   Nb add/s

0                        116
1                        108
2                        158
5                        208
10                       243
20                       270
50                       285
100                      303
200                      322
500                      357
1000                     400

As we can see, we are slightly slower when we send a transaction
operation for every add, compared to no transaction being sent (which is
kind of making sense, as we send 3 operations instead of one -
startTxn/add/endTxn vs add -).

When we gather 2 adds into one single transaction, we get an almost 50%
speed improvement, which tops around a 4x improvement when we gather
1000 adds within one single transaction.

Note that the test I run do commit every N addition, and I'm injecting
10000 entries total (numbers aren't changing significantly if I inject
100 000 entries, it's just that a run would take many minutes instead of
20s to 3mins).

So it does the job, and it improves performance.

Now, there is more work to do :
o rollback hasn't been tested yet
o we need to forbid concurrent writes while a transaction is being
executed - which means that a transaction is seen as one single giant
write - with the consequence that a rogue client starting a transaction
but never finishing it will potentially lock the server.
o a mechanism to protect the server against such rogues client has to be
implemented (could be a limitation in the number of update per
transaction and/or a time limit for a transaction). Note that while a
transaction is being conducted, nothing is flushed on disk.
o more tests are to be conducted (do we see entries being updated during
a transaction if we do a search aside the transaction ?)
o controls are not returned back atm, as they should

Otherwise, I have met some issues in other parts of the server whild
implementing transactions :

o for most of the operations, controls aren't sent back to the client
(except for the Bind Operation)
o We should write a <Operation>Decorator instead of a request/response
implementation, to avoid a call to a method that is a big switch doing
the exact same thing. This is a bit cleaner.

Also note that if the partition does not support transactions, then the
transaction requests are simply ignored.

I will commit the code when the previous listed points have been
fixed/implemented.

I do think we should leverage this extension when injecting a huge
number of entries into the server, like when using Studio to import a
LDIF file. I would suggest to gather updates in block of 100 to get a
good boost (x3) without blocking the writes for other clients for too
long (300ms).

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org