java和Mysql数据一致性_并发消费入库,保证数据一致性,一个mysql事务执行数据锁问题探讨...

在面临上游订单可能重复下单的问题时,保证数据库中只保留有效订单是一项挑战。本文探讨了三种解决方案:全局分布式锁、单订单分布式锁和依赖MySQL事务的无锁策略。通过实验,发现在特定情况下可能存在死锁问题,但通过调整SQL语句,可以降低死锁的概率。
摘要由CSDN通过智能技术生成

需求,

上游下单到mq,bms消费mq,将订单数据存入数据库中

(上游有可能重复下单.要求最后一条单有效.)

会开启多个消费者同时消费mq,因此可能上游下发了两条重复的订单数据,两个消费者同时各拿到一条,然后入库.

这种情况要保证,最后只有一条数据有效.数据库中订单使用逻辑列is_delete = 0表示有效.

方案一:使用一个分布式锁,这种方式所有的消费者会顺讯执行所有入库操作.

方案二"每个订单使用一个分布式锁,"这种情况下,只有重复单才会阻塞,不同单不会阻塞.但是要创建大量的分布式锁,要求锁的实现能抗并发.

方案三,应用层无锁,使用数据库的事务原理,利用数据库自身的锁,保证.

方案三的语句如下:

set autocommit=0;

begin;

update financial_freight_bill b set b.is_delete = 1 where b.bill_code = '1';  //语句一

insert into financial_freight_bill (bill_code,is_delete,cust_code) VALUES('1',0,"tran2"); //语句二

COMMIT;

ROLLBACK;

在navicat中打开两个窗口测试;

连接1 执行语句一

连接2 执行语句一

连接1 执行语句二 会阻塞

连接2 执行语句二 Deadlock found when trying to get lock;

前两个,不锁的,第三个开始阻塞,第四个死锁,mysql自动杀死锁,这时连接1获得锁无阻塞执行.

b.bill_code = '1' 这个查询时没有数据的.

可见该事务会出现死锁现象.导致其中一个事务的执行失败

与dba讨论后,语句改为

set autocommit=0;

begin;

UPDATE financial_freight_bill b

INNER JOIN (

SELECT

c.id

FROM

financial_freight_bill c

WHERE

c.bill_code = '1'

) cc ON cc.id = b.id

SET b.is_delete = 1;

INSERT INTO financial_freight_bill (

bill_code,

is_delete,

cust_code

)

VALUES

('1', 0, "tran1");

COMMIT;

只改了第一条语句,这样还是会出现死锁,通原来一样的结果,但是dba认为这样会好些,出现死锁概率会小.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值