富二代实习生碰到 PostgreSQL 死锁了:那就干脆跳过不锁呗!

数据库 PostgreSQL
在设计实现事务和监控应用程序性能时,通过应用最佳实践,您可以避免和解决 PostgreSQL 数据库中的死锁。在使用诸如 “SELECT ... FOR UPDATE SKIP LOCKED“ 这类技术时,请务必谨慎使用它,并严谨地测试您的应用程序。

事务

事务是构建数据库驱动的应用程序的基本组件。当一个事务开始后,它可以读取和修改数据库中的数据。当它修改数据时,它会获得对它正在更改的资源(如行或表)的锁定。该锁定可防止其他事务同时修改相同的资源,从而确保以一致且可预测的方式对数据进行更改。

但是,如果两个事务同时尝试访问或修改同一资源,则它们最终可能会陷入死锁情况,即在另一个事务释放其锁定之前,任何一个事务都无法继续进行。

最佳实践

为了避免死锁,在设计和实现事务时,遵循一些最佳实践非常重要:

• 避免长时间锁定资源:长事务和长时间运行的锁定可能会增加死锁的可能性。尽量保持事务简短,避免长时间持有锁。

• 优化查询:一个事务的查询应该是最优的,并尝试仅对必需的行执行操作。这样可以减少事务锁定的行数,并允许其他事务访问这些行。

• 确保更新以一致的顺序进行:确保相关资源的更新以一致的顺序进行。

• 避免显式锁定和表级锁:尽可能避免使用显式锁定或表级锁,因为表级锁会限制对整个表的任何操作,并阻止任何其他事务对其执行任何查询。

解决死锁

如果遇到死锁,解决死锁的第一步是,分析情况并确定所涉及的事务、它们争用的资源以及导致死锁的事件顺序。您可以使用 PostgreSQL 日志文件或查询 pg_stat_activity 系统视图,来收集此信息。您可以使用此信息来识别死锁中涉及的查询和资源。

确定所涉及的查询和资源后,可以检查它们,以确定是否可以根据最佳实践进行任何优化,以减少未来出现死锁的可能性。

PostgreSQL SKIP LOCKED 示例

如果需要从一个表进行 SELECT,并在事务完成之前保护这些行不被更新,则可以指定 FOR UPDATE,但如果某些行被锁定了,则可以指定 SKIP LOCKED 来告诉查询忽略这些行,只对它可以访问的任何行执行操作。

下面是如何使用 “SELECT ... FOR UPDATE SKIP LOCKED“ 的一个示例:

在会话 1 中:

BEGIN;

SELECT * FROM colours;
 id | name
----+-------
  1 | red
  2 | green
  3 | blue
(3 rows)

UPDATE colours SET name = 'scarlet' WHERE name = 'red';

在会话 2 中:

BEGIN;

SELECT * FROM colours FOR UPDATE NOWAIT;
ERROR:  could not obtain lock on row in relation "colours"

SELECT * FROM colours FOR UPDATE SKIP LOCKED;
 id | name
----+-------
  2 | green
  3 | blue
(2 rows)

在指定 SKIP LOCKED 选项,使用 SELECT ... FOR UPDATE 时,有几件事要记住。

• 应仅在多个事务可能同时尝试锁定相同行的情况下,才使用 SKIP LOCKED,并且需要可以接受某些事务能够跳过锁定的行。

• 如果使用不小心,跳过锁定的行可能会导致数据不一致。请确保应用程序逻辑可以处理跳过某些行的情况。

或者,我们也可以在使用 SELECT ... FOR UPDATE 时,指定 NOWAIT 选项。指定 NOWAIT 选项时,如果无法立即锁定选定的行,则语句将立即报告错误,而不是等待。它要求应用程序中有正确的错误处理逻辑。

总结

在设计实现事务和监控应用程序性能时,通过应用最佳实践,您可以避免和解决 PostgreSQL 数据库中的死锁。在使用诸如 “SELECT ... FOR UPDATE SKIP LOCKED“ 这类技术时,请务必谨慎使用它,并严谨地测试您的应用程序。

责任编辑:武晓燕 来源: 红石PG
相关推荐

2020-07-27 08:26:03

数据库 SQL索引

2017-08-09 17:58:27

甲骨文二代IaaS创新

2012-11-19 13:53:42

职场Google实习生

2010-09-16 15:19:12

2012-02-21 10:05:17

HTC王雪红

2014-01-07 09:23:41

项目管理

2024-05-27 00:30:00

2013-06-07 09:59:40

Google实习面试

2010-10-12 11:06:07

招聘

2009-09-17 09:35:17

微软实习生

2009-03-13 08:58:04

AOL裁员实习

2021-05-20 19:56:08

泄露密码数据泄露网络攻击

2024-01-09 15:51:56

Rust开发Trait

2015-04-14 15:05:35

Web前端开发腾讯暑期实习生

2011-12-07 20:37:42

iOSAndroid谷歌

2020-02-03 09:10:23

数据库删库删库跑路

2013-02-20 10:40:21

实习生科技公司谷歌

2013-11-26 14:15:43

2019-08-07 11:02:28

Python 开发编程语言

2012-11-07 17:05:41

Google实习生
点赞
收藏

51CTO技术栈公众号