From: | Alan Gutierrez <ajglist(at)izzy(dot)net> |
---|---|
To: | pgsql-general(at)postgresql(dot)org, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Ryan VanderBijl <rvbijl(at)vanderbijlfamily(dot)com> |
Subject: | Re: serialization errors |
Date: | 2003-01-30 15:51:47 |
Message-ID: | 200301300951.47196.ajglist@izzy.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
On Tuesday 28 January 2003 23:59, Tom Lane wrote:
> Ryan VanderBijl <rvbijl(at)vanderbijlfamily(dot)com> writes:
> > For adding a new node, I basically do this:
> > insert into tree_node(parent_id, node_order)
> > values(1, (select max(node_order)+1 from tree_node where parent_id =
> > 1) );
> That "select max()+1" makes me itch ;-) ... that's as perfect a recipe
> for concurrency problems as I can imagine.
For concurrent transactions, select max (node_order) + 1 will return the
same value for all concurrent transactions. The first transaction to
insert the value wins. Any other concurrent transaction will abort with
a duplicate key error.
Do this instead:
insert into tree_node (parent_id, node_order)
values (1, 0);
update tree_node
set node_order =
(select max (node_order) + 1
from tree_node as tn1
where tn1.parent_id = parent_id);
> At first glance it seems that all this is doing is assigning sequential
> node_order values to the children of any particular parent. Is it
> really necessary that those node_order values be consecutive? If they
> only need to be strictly increasing, you could use a sequence to
> generate them. (Actually, I think you could dispense with node_order
> entirely, and use the node_id field instead.)
>
> In any case, I'd suggest some careful thought about what your data
> structure really is, and how you could avoid creating serialization
> bottlenecks like this one.
In my application, I use select max to generate a sequential value for
concatenated key such as:
create table order_item (
firm_id integer not null references (firm),
patient_id integer not null,
prescription_id integer not null,
... -- script data
primary key (firm_id, patient_id, prescription_id),
foreign key (firm_id, patient_id) references (patient)
);
Creating a prescription id by select max + 1 in this case does not cause
a bottleneck, since it will only block other transactions that wish to
insert a prescirption for this particular patient. Not common in my
application.
If you are going to be inserting into trees frequently, you are more
likely to have a bottleneck, espcecially if different processes want to
insert into the same tree.
Alan Gutierrez - ajglist(at)izzy(dot)net
http://khtml-win32.sourceforge.net/ - KHTML on Windows
From | Date | Subject | |
---|---|---|---|
Next Message | Alan Gutierrez | 2003-01-30 16:00:45 | Re: serialization errors |
Previous Message | pginfo | 2003-01-30 15:47:57 | Re: URGENT: referential integrity problem |