问题
Please bear with me because I'm hopeless on vocabulary, and my own searches aren't going anywhere.
I've learned here that if I update in the way I want to here (with the GROUP_CONCAT
s also stored in user-defined vars), I'll lock the entire table.
I'm fairly certain the best way to do this would be to UPDATE
row by row in a CURSOR
, starting with the highest PK id then descending because I'm sure I will have a lower chance of a deadlock, or conflict, or whatever it's called (told you I was bad with the vocab) if I start from the most recent record.
The column being UPDATE
d has no index.
I just found out here that a TRIGGER
is a TRANSACTION
by default, so I will make a proc instead and call from php.
The transaction isolation level is REPEATABLE-READ
.
I'm more concerned with these overlapping UPDATE
s causing deadlocks with nothing happening than them taking time to complete.
All tables InnoDB.
All SELECT
s and UPDATE
s are WHERE
d on PK id except for the CURSOR
SELECT
which SELECT
s all ids in the table that's being UPDATE
d. No joins. No muss. No fuss.
That said, here finally are the questions:
- Will the
DECLARE
'sSELECT
onlySELECT
once, or does that also loop (I'd prefer it toSELECT
only once)? - Will the
DECLARE
'sSELECT
's lock remain for the duration of the proc (I'd prefer it to release asap)? - Will the row lock for each
UPDATE
release as soon as the query is finished, or will they remain for the duration of the proc (I'd prefer the row lock release after the individualUPDATE
query has finshed)? - Will the
SELECT
s for the user variables also release after they've been set (you guessed it: I prefer those also to release asap)? - Will it be possible to still
SELECT
the row beingUPDATE
d with the row lock (again, I'd prefer if I could)?
Many thanks in advance!
Why UPDATE
all on INSERT
In my website (in my profile), I allow users to access all submitted links ever. That's fine on a sequential basis, I simply reference the id.
However, I also rank them on a combined percentile of a custom algorithm on the the 3 vote types, equally weighting the 3.
The problem is that in my algorithm, each vote affects all other votes. There's no way around this because of the nature of my algorithm.
On Demand
I tried that route with PHP. No go. There's too much calculating. I'm not so concerned with users having accurate data instantly because the page will automatically update the ranks for the user with the user being non the wiser, but I can't have the user waiting forever because I allow rapid dynamic pagination.
Calculating in a view was an even greater disaster.
回答1:
- The
DECLARE
'sSELECT
will select only once, but I am afraid, that won't help you ... - The
SELECT
cursor might keep something locked fromOPEN
up toCLOSE
- what it is depends on your storage engine: It can be table, page, row or nothing - The
UPDATE
will lock for as long as the update takes. Again, depending on your storage engine, the lock can be table, page or row (but obviously not nothing)
But you might consider a completely different approach: IIUC, you basically want some ranking or percentile match and you try to do this by reacting to every INSERT
. This has a big problem in my POV: You calculate lots and lots of unneeded values. What would happen, if you calculate only on a reading operation?
- If there is allways exactly one
INSERT
between two reading operations, you have to recalculate allways - same case as if you calculate allways as now. - If there are no
INSERT
s between two reading operations, the MySQL query cache will have kept the result of the prior calculation and will not rerun the query, so you calculate less. - If there are more than one
INSERT
s between two reading operations, you need to calculate only once for N inserts.
So, calculating the rank/percentile on demand will never be more expensive than calculating on INSERT
, but it has the potential to be significantly cheaper.
来源:https://stackoverflow.com/questions/14224136/cursor-in-proc-that-only-locks-current-row-being-updated-while-updating-and-no