天天看点

PostgreSQL 使用advisory lock或skip locked消除行锁冲突, 提高几十倍并发更新效率

digoal

2016-10-18

postgresql , advisory lock , 高并发更新

通常在数据库中最小粒度的锁是行锁,当一个事务正在更新某条记录时,另一个事务如果要更新同一条记录(或者申请这一条记录的锁),则必须等待锁释放。

通常持锁的时间需要保持到事务结束,也就是说,如果一个长事务持有了某条记录的锁,其他会话要持有这条记录的锁,可能要等很久。

如果某张表的全表或者大部分记录要被更新的话,有几种做法。

1. 在一个事务中更新需要更新的记录,很显然时间可能很长,因为没有了并发。

2. 在多个事务中更新不同的记录,使用高并发来缩短更新的时间,但是就需要解决并发更新时存在的行锁冲突的问题。

本文将要给大家介绍两种解决并发更新行锁冲突问题的方法。

测试表,单条记录越大,更新单条记录的时间越久(例如更新亿级别的超长bit类型)。

每个人群都有一个唯一的id,即parallel_update_test.id。

测试数据

更新需求,每条记录都有更新

例如我存储的数组是userid,每条记录代表某个属性的人群数据,这个属性的人群数据不断的在变化,因此会不断的需要更新。

使用并发的手段提高更新效率。

所以只要保证并行的会话更新的是不同的id对应的数据即可,同时需要避免单次重复更新。

使用advisory lock可以避免并发更新同一条记录。

使用扫描式的获取advisory lock,保证不会重复获取即可。

代码如下:

设计上尽量保证id全局唯一,否则获取advisory lock的冲突可能性会增多。

测试,使用100个并行度

并行更新耗时4秒

这个方法需要9.5以及以上版本支持

使用100个并行度

在实时推荐系统中,通常可以使用数组或者比特位来标记人群,而每个人群都在不断的发生变化,也就是说,整张表都是热表。

为了提高更新的效率,本文给大家提供了两种并行消除行锁冲突更新的方法。

使用postgresql提供的skip locked 或者advisory lock特性,消除行锁冲突,提高并行度,从而提高更新效率,发挥机器的最大能力。

<a href="http://info.flagcounter.com/h9v1">count</a>