apache / incubator-seata

:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://seata.apache.org/
Apache License 2.0
25.25k stars 8.77k forks source link

when doing global rollback ,may cause an endless loop #6561

Open sixlei opened 4 months ago

sixlei commented 4 months ago

Ⅰ. Issue Description

if there is a table like CREATE TABLEt_test( uridint NOT NULL, namevarchar(64) DEFAULT NULL, PRIMARY KEY (urid), UNIQUE KEYt_test_name(name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; name is a uniquekey. and There is a piece of data in the table. (1,1) 1、global Transaction execute the sql "delete from t_test where id = 1", and this transaction need rollback 2、when rollbacking,other thread execute a sql like "insert into t_test values (2,1)" 3、that will cause the rollback thread endless loop.

Ⅱ. Describe what happened

that's because the range of the code "catch (SQLIntegrityConstraintViolationException e)" is too wide in AbstractUndoLogManager#undo and rollback of business will be catched by this. that should just catch "insertUndoLogWithGlobalFinished"

sixlei commented 4 months ago

If it is confirmed that it is not specially designed like this, I can mention pr to fix it.

funky-eyes commented 4 months ago

When data needs to be restored to a state before deletion, and its unique index is being used by other rows, do you think this data is unrecoverable? Should such data be restored in an incomplete state?

sixlei commented 4 months ago

It should be unrecoverable, at least from the point of view of seata. I think it can be treated as a dirty write operation, so that seata-server can keep the retry at a fixed frequency.

funky-eyes commented 4 months ago

It should be unrecoverable, at least from the point of view of seata. I think it can be treated as a dirty write operation, so that seata-server can keep the retry at a fixed frequency.

I agree with this approach. In fact, it is unrecoverable.

sixlei commented 4 months ago

It should be unrecoverable, at least from the point of view of seata. I think it can be treated as a dirty write operation, so that seata-server can keep the retry at a fixed frequency.

Then I'll mention a pr to fix it. Now this situation is an endless cycle because outside "for(;;)", and it should be possible to fix it.

LPBruce commented 3 months ago

@funky-eyes Please assign to me, I will fix it.

funky-eyes commented 2 months ago

@funky-eyes Please assign to me, I will fix it.

ok