系统中存在账户表,交易流水表,并发进行交易。处理过程是记流水表,更新账户余额。一个交易报文包含1笔到几百笔交易,另一交易报文可能包含和其报文相同的账户,交易报文之间存在干扰。在测试中,发现频发死锁,几乎无法运行。
死锁其实不是数据库问题,而是业务一致性问题。这个问题还是需要从业务场景去解决。例如是否允许出现脏读幻读等。如果可以的话就降低隔离级别。另一个方法是把一个UOW拆成多个UOW提交,减少死锁现象。这个同样是业务问题。
收起锁的作用是为了保证事物的一致性。
锁等待是正常的。
死锁是不正常的,是错误的业务逻辑导致的死锁。主要从业务着手。
查找死锁:
1、event monitor
关键字: Deadlocks with details history values
2、db2pdcfg -catch 911,2
关键字:db2cos
对于死锁,问题的源头在于合理的应用程序设计,可以通过event monitor for locking或者查看db2diag.log找到发生死锁的应用,然后修改相应的code
收起可以采用乐观锁来处理,可以基于数据库实现,也可以基于redis实现,比如基于redis的事务机制以及watch指令(CAS)实现乐观锁的过程。
所谓乐观锁,就是利用版本号比较机制,只是在读数据的时候,将读到的数据的版本号一起读出来,当对数据的操作结束后,准备写数据的时候,再进行一次数据版本号的比较,若版本号没有变化,即认为数据是一致的,没有更改,可以直接写入,若版本号有变化,则认为数据被更新,不能写入,防止脏写。
基于数据库实现可以借鉴以下思路:
a. 先执行select操作查询当前数据的数据版本号,比如当前数据版本号是27:
select id, resource, state,version from t_resource where state=1 and id=5780;
b. 执行更新操作:
update t_resoure set state=2, version=27, update_time=now() where resource=xxxxxx and state=1 and version=27
c. 如果上述update语句真正更新影响到了一行数据,那就说明占位成功。如果没有更新影响到一行数据,则说明这个资源已经被别人占位了。
收起