Thread Vs Transaction

Any body can explain it detail? When we use transaction and when we use
thread?

Thank you,
Reinhart

On May 11, 8:09 am, Rails T. [email protected]
wrote:

Any body can explain it detail? When we use transaction and when we use
thread?

That’s a slightly meaningless question since the 2 are not really
related, it’s like saying when should I use a toothbrush and should I
take a bus.
The point of a transaction is to ensure that a set of changes are
either all committed or none of them (no matter what happens). The
classic example is a money transfer. there are 2 changes (debit
alice’s account, credit bob’s account) and we want either both to fail
or both to succeed. We don’t alice to be debited but bob not credited.
Threads are when you need parallel units of execution. (you won’t see
them a lot in rails though since large chunks of rails are not
threadsafe)

Fred

Here what I want to ask.

I have some questions regarding my topic in this forum and here they
are:

[1] When and why we should use Thread as good implementation for our
application ? and the same question for Transaction.

[2] What are differences Thread and Transaction?

[3] How we can prevent DeadLock in ActiveRecord?

[4] How I can put Time Record for my Log, specially in test.log for each
its line?

Thank you for your helps and suggestions.

Sincerely,
Reinhart

Rails T. wrote:

Here what I want to ask.

I have some questions regarding my topic in this forum and here they
are:

[1] When and why we should use Thread as good implementation for our
application ? and the same question for Transaction.

Transactions are related to state, threads to process. Transactions are
used to force logical atomicity when the data store implementation
breaks the state transformation into multiple discrete parts. The
common example is that of a funds transfer between accounts as given
above.

Threads are used when activity can be safety detached and allowed to
complete without the parent process having to wait. An example would be
starting a file upload, detaching that process as a thread and
immediately returning the focus to the UI allowing the user to perform a
different action without waiting until the upload completes.

As mentioned above, the current implementation of Rails makes the use of
threads inherently unsafe and problematic.

[2] What are differences Thread and Transaction?

Thread is for processes, transactions are for data.

[3] How we can prevent DeadLock in ActiveRecord?

By default, ActiveRecord does not perform any locking so the issue does
not arise. If you implement row locking by adding the magic attribute
lock_version then you get optimistic locking based on version tracking
and again, a deadlock is not possible.

[4] How I can put Time Record for my Log, specially in test.log for each
its line?

See:http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging

specifically:

class Logger
def format_message(severity, timestamp, progname, msg)
“#{timestamp} (#{$$}) #{msg}\n”
end
end

Google is your friend.

On May 11, 5:02 pm, Rails T. [email protected]
wrote:

Here what I want to ask.

I have some questions regarding my topic in this forum and here they
are:

[1] When and why we should use Thread as good implementation for our
application ? and the same question for Transaction.

[2] What are differences Thread and Transaction?
Like I said before, threads and transactions are just completely
different things. What’s the difference between a cucumber and a
capitalism ?

Fred

James B. wrote:

See:http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging

specifically:

class Logger
def format_message(severity, timestamp, progname, msg)
“#{timestamp} (#{$$}) #{msg}\n”
end
end

Be sure to read the entire article and determine which parts are
applicable to the version of Rails that you are using.

On 11 May 2008, at 22:41, James B. wrote:

[3] How we can prevent DeadLock in ActiveRecord?

By default, ActiveRecord does not perform any locking so the issue
does
not arise. If you implement row locking by adding the magic attribute
lock_version then you get optimistic locking based on version tracking
and again, a deadlock is not possible.

That’s not entirely true (see
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html)
.
The database itself clearly requires a lock of some sort of place
while running an update for example, 2 things trying to update the
same thing under the right conditions can give rise to a deadlock.

Fred

James B. wrote:

By default, ActiveRecord does not perform any locking so the issue does
not arise. If you implement row locking by adding the magic attribute
lock_version then you get optimistic locking based on version tracking
and again, a deadlock is not possible.

What is the meaning of attribute lock_version? I was no problem when i
used lock like :

ModelName.find(params[:id], :lock=>true),

But when i change to be :

ModelName.find(:all, :lock=>true, :conditions[“expired_at > ?”,
Time.now])

The DeadLock is always happened.

Google is your friend.

Only small articles explained detail about Transaction and Lock in
Theory. By The way, thanks for your cooling answer in all my questions.

Looking for your next respond

Reinhart
http://teapoci.blogspot.com

I am not sure where exactly you are coming from, but if you are
reading a lot about threads when dealing with database deadlocks, a
thread is short hand for “some process that asks the DB for data”.
For example, two Rails servers hitting the same database would be
termed as “two threads” even though they are really entirely different
programs on different machines. What they mean by “threads” is
internal to the database program… each connection to a MySQL server
has it’s own internal thread inside MySQL (confusing, huh?). Others
have explained transactions, so I won’t go into that here.

In general, my advice on locking is don’t. 9/10 of the time you don’t
need it. Why are you locking on find in the first place? You do
realize this probably locks the entire table in the second case,
right? You should only lock when you are worried specifically about
bad (not incomplete or the latest and greatest… they can run the
query again if they want to get the last 30 seconds of data) data
coming back to the user, or an inconsistent state. The reason
deadlocks happen on the latter query is because you are scanning the
entire table (effectively building up a temporary table in memory out
of the condition in the where clause). This takes longer, making
deadlocks more likely. All this is besides the fact that you should
almost never use table locks with InnoDB, since table locks and row
locks are handled by two different systems internally (and thus they
don’t always know about each other’s locking… see the documentation
for details).

  1. Make sure you are using InnoDB tables (Rails does this by default.
    If you aren’t using MySQL, check your documentation). They are much
    better at managing locks.
  2. Don’t issue lock statements unless you are running into problems.
    99% of the time, the database knows when and when not to lock
    (especially with InnoDB).
  3. Don’t lock on select unless you are absolutely sure you need it,
    since selects are usually 90% of your application. If you need to
    lock the returned records (i.e. you are going to update them and you
    don’t want anyone else messing with them), use FOR UPDATE or an
    equivalent lock that locks records and not tables. You may also look
    into LOCK IN SHARE MODE if you are looking for consistent reads in a
    transaction.
  4. If you use transactions, order your table accesses in the same
    order in every transaction (I use alphabetical order myself for
    simplicity). Deadlocks usually occur under this condition:

Query A locks table A
Query B locks table B
Query A tries to lock table B and fails
Query B tries to lock table A and fails
Both queries deadlock.
If they tried to access these same tables, except in the same order as
the other query, the deadlock does not occur.

  1. Always check the debug output from rails and the internal DB logs
    to ensure you are running the queries you think you are running.
    Since there is no one-to-one mapping between AR’s semantics and (My|MS|
    Postgre)SQL’s, the actual query text for advanced queries may not be
    what you expect. For example, what kind of lock does AR use in this
    case, assuming MySQL backend? Who knows? Caveat emptor.

  2. SHOW ENGINE INNODB STATUS - the #1 tool for solving deadlock
    issues.

The MySQL documentation should help you find out where you are going
wrong (RTFM baby!).

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html

On May 12, 3:16 am, Rails T. [email protected]

On Mon, May 12, 2008 at 7:51 PM, Rails T.
[email protected] wrote:

else
end
lock_version in barang_terpesans table. but still not work (inconsistent
data is always happened.)

Calls to the database driver block until results are available. You
can easily deadlock Ruby threads if you request & obtain a mysql lock
in one thread then request the same lock in another thread: the
database driver in the second thread will block until the mysql lock
is released, but the first thread will be blocked by the second
thread, unable to complete its work and release the mysql lock.

This can be solved by using multiple processes instead of multiple
threads, by serializing database access across all threads, by using a
pure-Ruby database driver, or by using the native postgresql or oracle
drivers which support nonblocking db calls when you enable
ActiveRecord::Base.allow_concurrency.

Best,
jeremy

I implement it :

class BarangTerpesan < ActiveRecord::Base

def self.hitung_item_dikotak(kode_barang, hari_h, hari_out)
if hari_out != nil
barang = find(:all, :conditions => [“barang_id = ? AND hari_out > ?
AND hari_h <= ?”,kode_barang, hari_h, hari_out], :lock=>true)

else
barang = find(:all, :conditions => [“barang_id = ? AND hari_h =? AND
hari_out IS NULL”, kode_barang, hari_h], :lock=> true)

end

barang.inject(0){|x,y| x + y.jumlah}

end


end

And here is my test.log about dead lock :

http://pastie.org/195865

And here’s the code for pesimistic :lock => true
http://pastie.org/195869

I tried implementing optimistic lock by adding ‘magic’ column
lock_version in barang_terpesans table. but still not work (inconsistent
data is always happened.)

Thank yOu

Reinhart

Clever N., thank you for your references theory. but those
references are teaching the way transaction in store procedure. But i
need the way rails handle deadlock.

Rails has 2 key types, they are optimistic lock and pesimistic lock. I
used pesimistic lock such as a ‘:lock=>true’ to handle inconsistency
data into focus table (barang_terpesans). But if i trid .find(:all,
:lock=>true, :conditions=>[…]) it is always DeadLock.

I was trying an optimistic lock by adding lock_version column in
barang_terpesans table but still can’t handle inconsistency data. I
tried like it :

http://www.ruby-forum.com/topic/61754

I hope some one can help me in handle deadlock in rails way.

Thank you again very much,
Reinhart

Clever N. wrote:

The reason
deadlocks happen on the latter query is because you are scanning the
entire table (effectively building up a temporary table in memory out
of the condition in the where clause). This takes longer, making
deadlocks more likely. All this is besides the fact that you should
almost never use table locks with InnoDB, since table locks and row
locks are handled by two different systems internally (and thus they
don’t always know about each other’s locking).

The MySQL documentation should help you find out where you are going
wrong (RTFM baby!).

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html

I am interested with your statement above, because that is exactly
happened to me. Ok let’s forget about deadlock first. I do experiment
for 2 transaction with same code in rails way here is my code :
http://pastie.org/195869

And here is my ActiveRecord Which is containing LOCK.
http://pastie.org/195875

And the problem now when 2 concurrent process run, each transactions
take exclusive lock and execute it, the theory said that if one
exclusive lock is taken another transaction which is wanting exclusive
lock should wait till the previous lock is released.

Here is my record of log : http://pastie.org/195865

at lines 16 - 21 in Log : Transaksi 1 grant exclusive lock

at lines 50 - 55 in Log : Transaksi 2 grant Exclusive too, whereas
Transaksi 1 is not released it.

at lines 83 - 89 in Log : Transaksi 2 gets DeadLock

My question now :
“Why Transaction 2 can grant exclusive lock while Transaction 1 still
not release the exclusive lock.?”

Thank you.

-=-=-=-=-=-=-=-=-=-=-=-
ABOUT DEADLOCK :
I can put announcement there by using :

Begin

rescue
flash[:notice] = “Your process can be completed, please try again.”
end

On May 13, 2:39 am, Rails T. [email protected]
wrote:

I am interested with your statement above, because that is exactly
happened to me. Ok let’s forget about deadlock first. I do experiment
for 2 transaction with same code in rails way here is my code :http://pastie.org/195869

I’ve never seen a deadlock on a single table like that, and I am not
positive why it’s doing that either. But I am wondering why you are
locking at all when you aren’t updating the very records you are
locking. Something tells me you really don’t need those locks. But
it’s your code, so if you want to fix the issue, in that rescue
clause, simply re-call the method it’s in again, and retry the
transaction (for, say, 3 times or so). If you get deadlocks all the
time, you need to rethink your locking scheme, and maybe loosen your
restrictions on just how accurate the data needs to be. If you are
trying to keep “jumlah” , that sum you are finding in one of your
queries, consistent, maybe make another table that keeps track of that
variable, and simply use decrement and increment statements (i.e. SET
value = value + 1), then you don’t have to worry about locking on that
value, since it’s never actually manually written to (just increased
or decreased).

Those are the only two solutions I can think of at the moment, and
without knowing exactly what these table names mean, I am kind of
stabbing in the dark as to what you are trying to accomplish.