自学内容网 自学内容网

truncate锁表问题

truncate锁表问题

背景

项目中使用了GreenPlum数据库集群,Greenplum是一个OLTP数据库,实际上内置了PostgreSQL数据库。

需求是这样的,订单系统需要我们组提供用户唯一标识的数据,数据分为两部分,一部分是用户唯一标识的订单详情,另一部分是用户唯一表示的聚合数据。数据包括用户的唯一标识,商品数,售后商品数,支付时间,支付金额,退款金额,总订单数,退款订单数等等吧。

用户唯一标识根据用户的手机号,收货地址等生成的。也就是说同一个用户的手机号没变,但是另一个用户使用了该用户的手机下单,地址变了,用户唯一标识也会改变。

明细表大约有个九千万的数据,聚合汇总表有两千万数据。数据每天是全量重新跑一次。每天会truncate表,然后重新的写入。

主要是用来配置售后策略,来标识失信人和用户的售后发生率。用户每次下单都会回调我们的接口来查询数据,来判断用户是不是失信人。当天下单的新用户可能会没有唯一标识数据,所以订单系统会使用定时任务,每天八点~凌晨两点批量调用我们的接口,来给数据打上标识,如果第一次没有查询到唯一标识的数据,后面不会再次执行。因为我们的数据每天跑一次。

事情经过

问题发现

功能是年前上的,运行了大约两个月,没啥问题。后来一天早上数据的同学反馈 ,数据写入失败了,需要重新推数据。后来几次也是失败了,之后就是运维同学反馈,GP集群一直告警,主从切换失败,集群挂掉了。后来在数据库监控看有大量的查询oneid数据的请求被阻塞了。连接无法释放,拖垮了我们的集群。最终导致我们的服务也不可用了。

问题确认

gp集群挂掉,服务无法使用。

快速相应

重启数据库集群,暂停数据的写入,先保证服务可以正常访问。

问题分析

为什么会这样了,难道是慢查询拖垮了我们的数据库?

之前已经为表创建了索引,八千万数据大约200ms。排除这一原因。

后来数据的同学反应,他是每天早上truncate表,然后全量重新写入数据。于是查看了pg的官方文档,发现TRUNCATE 获取其操作的每个表的 ACCESS EXCLUSIVE 锁,该锁会阻止对该表的所有其他并发操作。

TRUNCATE 获取其操作的每个表的 ACCESS EXCLUSIVE 锁,该锁会阻止对该表的所有其他并发操作。当指定 RESTART IDENTITY 时,任何要重新启动的序列同样会被独占锁定。如果需要对表进行并发访问,则应改用 DELETE 命令。

https://postgresql.ac.cn/docs/current/sql-truncate.html

根据我们的数据库监控,还有服务的日志分析,发现我们的oneid接口被调用的特别频繁,每秒有2000多次。而且大部分的查询连接都没有释放,一直在等待。

问题复现

我们没有uat环境,只有test环境,两个环境数据量,配置啥的天差地别。

加配置,跑数据,复现问题。

在我们和运维同学的不懈努力下,最终复现了问题。

根本原因

就是因数据库操作不当,导致整个表被锁住,然后并发请求来了,就被阻塞,无法返回,无法释放连接,最终导致连接数被耗尽,拖垮了集群。

解决方案

临时方案

  1. 通知订单系统,暂时停止售后策略的回调,还有定时任务的调用。
  2. 重新写入数据。
  3. 调整数据写入任务的事件,调到凌晨3点。避免truncate操作,时会有大量的并发查询操作。
  4. 通知订单,重新调用。
  5. 服务正常。

最终方案

使用StarRocks的主键模型,代替每次truncate后再insert操作。

详情表使用oneid作为主键,然后添加分区配置,每天创建一个分区,设置分区的过期时间。数据每天都会重新写入一个新的分区,老的分区会被删除。

聚合汇总表也是这样。

starrocks是OLAP数据库,主键模型,可以不用删除,主键相同直接更新,这样就避免了truncate操作。

验证和监控

在测试环境跑了一段时间,发现没有问题,然后切到生产环境。

监控了大约一个月也都是正常的。

复盘总结

本次事故,主要是因为

  • 数据库特新掌握的不够,加上操作不当。
  • 接口对接设计的时候没有沟通的很详细。以为就是单纯的提供一个接口即可,没有后续的那么多的策略和定时任务啥的,没有评估好接口的处理能力。
  • 好在处理及时,没有造成很大的影响

总结

本次问题是我入职一个多月的时候发生的,我们项目用的技术比较杂,有StarRocks,GreenPlum,Clickhouse,ES,Hbase都有,我也不知道为啥这样,就是都用了。

  1. 在使用一种新的技术的时候一定要做好调研,多查阅一些资料,看有没有什么坑,可以尽量的规避掉。(我们也不算新技术,在入职之前,好像一直在用)
  2. 需求对接的时候一定要聊清楚具体的场景,使用方式,调用量,时间段等等吧,看具体的需求。
  3. 一定要做好测试,尽量要有一个UAT环境,对标生产环境的,来提前发现问题,提前暴露问题,提前解决,不要把问题带到生产。

暂时先想到这几点,有好的建议大家可以提出来,一起进步,一起变强。


原文地址:https://blog.csdn.net/Y_eatMeat/article/details/142353385

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!