Closed xqdd closed 1 year ago
seata server日志发出来
把performance_schema打开看看更详细的内容,这两条sql没有看出有什么锁定冲突,但实际上产生了死锁,怀疑数据库bug,修改为rc隔离级别可能会解决问题,执行show index from lock_table 截图给我看下结果
是不是频繁删除和插入?S锁和X锁打架,mysql的5.7和8本身都有这种问题 https://bugs.mysql.com/bug.php?id=68021 https://bugs.mysql.com/bug.php?id=21356
把performance_schema打开看看更详细的内容,这两条sql没有看出有什么锁定冲突,但实际上产生了死锁,怀疑数据库bug,修改为rc隔离级别可能会解决问题,执行show index from lock_table 截图给我看下结果
Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
lock_table | 0 | PRIMARY | 1 | row_key | A | 0 | null | null | BTREE | YES | null | |||
lock_table | 1 | idx_status | 1 | status | A | 0 | null | null | BTREE | YES | null | |||
lock_table | 1 | idx_branch_id | 1 | branch_id | A | 0 | null | null | BTREE | YES | null | |||
lock_table | 1 | idx_xid | 1 | xid | A | 0 | null | null | YES | BTREE | YES | null |
seata server日志发出来
这个日志得申请一下,暂时还导不出来
是不是频繁删除和插入?S锁和X锁打架,mysql的5.7和8本身都有这种问题 https://bugs.mysql.com/bug.php?id=68021 https://bugs.mysql.com/bug.php?id=21356
最高TPS=2左右,每次全局事务涉及10个表,这样算插入或删除lock_table的QPS=20,不算特别频繁吧?
索引看着没问题,大量用户反馈该问题的后续跟进反馈结果是正常了,可能跟mysql版本有关,这个sql是常见的不能再常见的sql了,delete只有一个条件xid,之前的死锁是xid 和in branchid导致的,拆分开后给xid单独加上索引就没这个问题了,你可以先改成rc读已提交为数据库的默认隔离级别来观察一段时间
索引看着没问题,大量用户反馈该问题的后续跟进反馈结果是正常了,可能跟mysql版本有关,这个sql是常见的不能再常见的sql了,delete只有一个条件xid,之前的死锁是xid 和in branchid导致的,拆分开后给xid单独加上索引就没这个问题了,你可以先改成rc读已提交为数据库的默认隔离级别来观察一段时间
好的,感谢,我再研究一下
@a364176773 复现了,mysql数据库版本8.0.31,事务隔离级别RR
CREATE TABLE `lock_table` (
`row_key` varchar(512) NOT NULL,
`xid` varchar(128) DEFAULT NULL,
PRIMARY KEY (`row_key`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
insert into lock_table (row_key, xid)
values
('lock:10', 'tx:1'),
('lock:20', 'tx:1'),
('lock:30', 'tx:1'),
('lock:40', 'tx:1'),
('lock:50', 'tx:1'),
('lock:60', 'tx:1'),
('lock:70', 'tx:1'),
('lock:80', 'tx:1'),
('lock:90', 'tx:1');
insert into lock_table (row_key, xid) values('lock:21', 'tx:2');
delete
from lock_table
where xid = 'tx:1';
insert into lock_table (row_key, xid) values('lock:19', 'tx:2');
我也是8.0.31 没有复现
隔离级别索引也完全与你一致
@a364176773 用一下我给的数据
delete
from lock_table
where xid = 'tx:1';
insert into lock_table (row_key, xid, branch_id)
values ('lock:10', 'tx:1', '1'),
('lock:20', 'tx:1', '1'),
('lock:30', 'tx:1', '1'),
('lock:40', 'tx:1', '1'),
('lock:50', 'tx:1', '1'),
('lock:60', 'tx:1', '1'),
('lock:70', 'tx:1', '1'),
('lock:80', 'tx:1', '1'),
('lock:90', 'tx:1', '1');
------分隔线---
insert into lock_table (row_key, xid,branch_id) values('lock:21', 'tx:2','2');
insert into lock_table (row_key, xid,branch_id) values('lock:19', 'tx:2','2');
https://github.com/seata/seata/assets/20871761/947b9291-826a-4503-9666-d413767990ae
应该是间隙锁或next key锁导致的,具体原因我还在研究
应该是间隙锁或next key锁导致的,具体原因我还在研究
我也怀疑是这个问题,你试着改成rc隔离级别,是不是就复现不出来了
@a364176773 用一下我给的数据
delete from lock_table where xid = 'tx:1'; insert into lock_table (row_key, xid, branch_id) values ('lock:10', 'tx:1', '1'), ('lock:20', 'tx:1', '1'), ('lock:30', 'tx:1', '1'), ('lock:40', 'tx:1', '1'), ('lock:50', 'tx:1', '1'), ('lock:60', 'tx:1', '1'), ('lock:70', 'tx:1', '1'), ('lock:80', 'tx:1', '1'), ('lock:90', 'tx:1', '1'); ------分隔线--- insert into lock_table (row_key, xid,branch_id) values('lock:21', 'tx:2','2'); insert into lock_table (row_key, xid,branch_id) values('lock:19', 'tx:2','2');
Clipchamp.mp4
好,晚点我试下
应该是间隙锁或next key锁导致的,具体原因我还在研究
我也怀疑是这个问题,你试着改成rc隔离级别,是不是就复现不出来了
是的,RC没这个问题
@a364176773 原因应该知道了:
当表中索引区分度很低并重复值达到一定条数时候,delete操作不会走索引,走的是全表扫描
根据InnoDB事务锁系统及其实现这里给出的结论
RR+无索引
在Repeatable Read隔离级别下,如果进行全表扫描的当前读(可能是没有索引,也可能是有索引,但是查询计划并没有走索引),那么会对主键索引上的所有记录加上next key locks,对supremum加上next key locks,对满足条件的记录的索引加上记录锁(lock_x | lock_rec_not_gap),杜绝所有的并发 更新/删除/插入 操作。
此时的delete操作会尝试将整个表数据都加上next key锁,并且观察到加这个锁是按顺序的,那么可以复现我们的场景:
insert into lock_table (row_key) values(1); insert into lock_table (row_key) values(5); insert into lock_table (row_key) values(10);
insert into lock_table (row_key) values(7);
这时候事务a持有主键值为7的记录锁
此时区分度过低,delete操作走的全表扫描,会尝试全表加next key锁,按顺序的话,会锁(-∞,1]、(1,5],然后遇到了事务a持有的7的记录锁,只会锁间隙(5,7),这时候会等待事务a释放记录锁
这时候发现事务b持有(1,5]的next key锁,触发死锁
RC隔离级别下没问题的原因是此时的delete操作不会锁间隙
我们计划将server的connection全部设置为rc,因为rr的特效对server其实是没有用到,rr效率也比rc低,如果你感兴趣的话可以尝试认领这个任务去提交pr,这样就对这个问题的死锁基本上一劳永逸了
我们计划将server的connection全部设置为rc,因为rr的特效对server其实是没有用到,rr效率也比rc低,如果你感兴趣的话可以尝试认领这个任务去提交pr,这样就对这个问题的死锁基本上一劳永逸了
周末可以试试
我们计划将server的connection全部设置为rc,因为rr的特效对server其实是没有用到,rr效率也比rc低,如果你感兴趣的话可以尝试认领这个任务去提交pr,这样就对这个问题的死锁基本上一劳永逸了
周末可以试试
好,那先把这个任务交给你啦,有问题再沟通
Ⅰ. Issue Description
释放全局锁时有死锁发生,偶现
Ⅱ. Describe what happened
Ⅲ. Describe what you expected to happen
框架不应该出现死锁
Ⅳ. How to reproduce it (as minimally and precisely as possible)
暂未验证
Ⅴ. Anything else we need to know?
server端1.5.2遇到过,升到1.6.1问题依旧 表结构
Ⅵ. Environment:
java -version
): jdk8uname -a
): linux