The basic problem you have is that everything is recursive and you are attempting to lock pages of data in InnoDB, creating lots of [**MVCC**][1] info. In some case, you may have attempted to lock the same InnoDB page repeatedly. That explains the deadlocks. I have commented on this situation deeply with someone in three separate posts on this same issue:

- https://dba.stackexchange.com/questions/3179/trouble-deciphering-a-deadlock-in-an-innodb-status-log/3185#3185
- https://dba.stackexchange.com/questions/3223/will-these-two-queries-result-in-a-deadlock-if-executed-in-sequence/3224#3224
- https://dba.stackexchange.com/questions/3302/reasons-for-occasionally-slow-queries/3305#3305


You need a workaround. You may want to try the following algorithm:

For this example

- id = 12
- amount = 22.75

Step 01) Make a table to collect all father_ids to be updated

    DROP TABLE IF EXISTS fathers_to_update;
    CREATE TABLE fathers_to_update
    (
        father_id INT NOT NULL,
        PRIMARY KEY (father_id)
    );

Step 02) Making a table that will be a FIFO queue. Put the value of 12 into the queue:

    DROP TABLE IF EXISTS fathers_to_queue;
    CREATE TABLE fathers_to_queue
    (
        father_id INT,
        id INT NOT NULL AUTO_INCREMENT,
        PRIMARY KEY (id)
    );
    INSERT INTO fathers_to_queue (father_id) VALUES (12);

Step 03) Get the Count of `fathers_to_queue`

    SELECT COUNT(1) FROM fathers_to_queue;

If the count is 0, goto Step 07)

Step 04) Remove the front number in `fathers_to_queue`

    SELECT MIN(id),father_id INTO @frontndx,@dad FROM fathers_to_queue;
    DELETE FROM fathers_to_queue WHERE id = @frontndx;

Step 05) Collect all father_ids from 161_ft_individual whose id is @dad into the queue

    INSERT INTO fathers_to_update SELECT father_id FROM 161_ft_individual WHERE id = @dad;
    INSERT INTO fathers_to_queue (father_id) SELECT father_id FROM 161_ft_individual WHERE id = @dad;

Step 06) Go back to Step 03

Step 07) Perform a single UPDATE of all records in 161_ft_individual you collected in `fathers_to_update` 

    UPDATE fathers_to_update A
    LEFT JOIN 161_ft_individual B
    USING (father_id)
    SET B.total_leg=B.total_leg+@amount;

That's it. I basically performed a preoder tree traversal back up the hierarchy to all records until father_id was NULL, which makes Step 03 stop collecting father_ids.

Give it a Try !!!

**UPDATE 2011-12-16 12:18 EDT**

Back on October 24, 2011, I actually wrote an algorithm in the MySQL Stored Procedure language to perform preorder tree traversal: https://dba.stackexchange.com/questions/7147/find-highest-level-of-a-hierarchical-field-with-vs-without-ctes/7161#7161. Hope it helps !!!

  [1]: http://en.wikipedia.org/wiki/Multiversion_concurrency_control