Skip to main content
replaced http://dba.stackexchange.com/ with https://dba.stackexchange.com/
Source Link

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 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:

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: Find highest level of a hierarchical field: with vs without CTEsFind highest level of a hierarchical field: with vs without CTEs. Hope it helps !!!

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 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:

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: Find highest level of a hierarchical field: with vs without CTEs. Hope it helps !!!

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 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:

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: Find highest level of a hierarchical field: with vs without CTEs. Hope it helps !!!

added 304 characters in body
Source Link
RolandoMySQLDBA
  • 184.3k
  • 33
  • 323
  • 531

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 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:

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: Find highest level of a hierarchical field: with vs without CTEs. Hope it helps !!!

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 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:

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 !!!

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 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:

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: Find highest level of a hierarchical field: with vs without CTEs. Hope it helps !!!

added 205 characters in body
Source Link
RolandoMySQLDBA
  • 184.3k
  • 33
  • 323
  • 531

The basic problem you have is that everything is recursive and you are attempting to lock pages of data in InnoDB, creating lots or MVCCof MVCC 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 for theon this same issue:

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 whoseuntil father_id was NULL, which makes Step 03 stop collecting father_ids.

Give it a Try !!!

The basic problem you have is that everything is recursive and you are attempting to lock pages of data in InnoDB, creating lots or MVCC info. In some case, you may have attempted to lock the same InnoDB page repeatedly.

  I have commented on this situation deeply with someone in three separate posts for the same issue:

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 whose father_id was NULL.

Give it a Try !!!

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 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:

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 !!!

added 205 characters in body
Source Link
RolandoMySQLDBA
  • 184.3k
  • 33
  • 323
  • 531
Loading
Source Link
RolandoMySQLDBA
  • 184.3k
  • 33
  • 323
  • 531
Loading