前面的文章我们提到HANA数据库表21亿上限问题以及表分区,今天我们就聊一聊我们在项目中遇到的表分区问题。
我们对于ACDOCA表做分区时,采用了一级Hash分区,二级Range分区的方式,但是在我们进行大批量并发冲销凭证的时候,发生了死锁现象。冲销一张凭证从1~2秒增加到几分钟甚至几十分钟的时间。通过SM13查看更新请求时,发现堆积了N多的请求,点看明细查看得知,全都卡在了Update ACDOCA上。
正常过账时时间消耗没多大影响,而冲销凭证过程包含产生新凭证和更新老凭证的过程,从SM13看发现全卡在更新老凭证上。没分区前我们更新不会这么久,所以我们对分区产生了质疑,分区是否合理?
在ACDOCA表采用一级哈希分区、二级范围分区的情况下,凭证冲销时出现死锁,我们推测可能由以下几种原因导致:
1. 事务并发操作
Ø资源竞争:在凭证冲销过程中,多个事务可能同时尝试访问和修改 ACDOCA 表中的相同或相关记录。例如,不同的用户可能同时对同一公司代码或同一会计期间的凭证进行冲销操作。由于采用了分区策略,事务可能会锁定不同分区中的记录,但如果这些分区中的数据存在关联,就可能导致死锁。
Ø操作顺序不一致:不同事务对表中记录的操作顺序不一致也可能引发死锁。比如,事务 A 先锁定分区 A 中的记录,再尝试锁定分区 B 中的记录;而事务 B 先锁定分区B 中的记录,再尝试锁定分区 A 中的记录。当两个事务都在等待对方释放锁时,就会形成死锁。
2. 锁的粒度问题
²锁的范围过大:如果在凭证冲销过程中,系统使用了过大的锁粒度,例如对整个分区或多个分区进行锁定,而不是只锁定需要修改的具体记录,就会增加死锁的风险。因为其他事务可能因为无法获取所需的锁而被阻塞,从而导致死锁的发生。
²锁的持有时间过长:如果事务在执行过程中长时间持有锁,而其他事务需要等待该锁的释放才能继续执行,就会增加死锁的可能性。例如,在凭证冲销过程中,如果某个事务在进行复杂的计算或数据验证时持有锁,而其他事务需要访问相关数据,就可能导致死锁。
3. 分区设计不合理
u数据分布不均:虽然采用了哈希分区和范围分区,但如果数据在分区中的分布不均匀,某些分区可能会成为热点分区,即多个事务频繁访问和修改这些分区中的记录。在凭证冲销时,热点分区中的锁竞争会更加激烈,从而增加死锁的风险。
u分区键选择不当:如果分区键的选择不合理,导致相关数据分散在不同的分区中,而凭证冲销操作需要同时访问这些分区中的数据,就会增加事务之间的锁冲突和死锁的可能性。
ACDOCA 表不使用哈希分区的核心原因是业务需求与哈希分区特性不匹配,其高频的范围查询、复杂连接和数据增长特性,更适合多级分区(范围 + 哈希)。哈希分区仅适用于等值查询为主、数据分布均匀的场景,而 ACDOCA 的业务场景远超这一限制。
SAP notes推荐的是范围 + 哈希分区,以FISCYEARPER字段进行range分区,我们目前正在调整方向,重新设定ACDOCA表的分区,等待新分区调整结束之后,再验证并发大批量冲销凭证看看分区是否合理。