使多个用户访问 PSQL 数据库
Making multiple users access to PSQL database
我是这方面的菜鸟,我所做的只是为一个用户连接到数据库,所以我不熟悉让多个用户访问数据库。
我的情况是:10 个设施将使用我的程序记录工人进出的时间,数据库将在主服务器上,而我在 programming/testing 该程序时所做的只是一个用户。我的问题是:多个远程位置是否可以使用一个用户连接数据库(应该不会发生冲突,因为他们都在写不同的东西,但在同一张表上)如果不是这样,我该怎么办?
好的关系数据库处理得很好,它是关系数据库中事务的所谓 ACID 属性中的“我”;它代表 隔离.
通过 locks 保护并发进程不会同时写入相同的 table 行,这会阻止其他事务,直到一个事务完成写入。
通过 multiversion concurrency control (MVCC) 保护读者免受并发写入,它保留旧版本的数据为读者服务,而不会阻塞任何人。
如果您将所有属于同一事务的数据修改包含在一个事务中,以便它们自动(ACID 中的“A”)发生,并且您的事务简单而简短,您的应用程序可能会正常工作。
如果不满足这些条件,可能会出现问题:
如果您的数据修改不受事务保护,则并发会话可能会看到不同会话的中间、不完整结果,从而处理不一致的数据。
如果您的交易很复杂,交易中后面的语句可能会以间接方式依赖前面语句的结果。这个假设可以被修改数据的并发 activity 打破。有以下三种方法:
悲观锁定:在您第一次使用它们时锁定所有数据 SELECT ... FOR UPDATE
这样在您的事务完成之前没有人可以修改它们。
乐观锁定:不锁定,但每当您第二次访问数据时,检查是否没有其他人在此期间修改过它们。如果是这种情况,请回滚事务并重试。
使用像 REPEATABLE READ
和 SERIALIZABLE
这样的高事务隔离级别,这可以更好地保证您正在使用的数据不会同时被修改。如果数据库不能保持保证,您必须准备好接收序列化错误,在这种情况下,您必须回滚事务并重试。
这些技术以不同的方式实现相同的目标。讨论何时使用哪个超出了这个答案的范围。
如果你的事务很复杂and/or需要很长时间(要尽可能避免长事务,因为它们会导致数据库中出现各种问题),你可能遇到 死锁,这是两个事务以一种“死拥抱”的方式相互锁定。
数据库将检测到这种情况并中断其中一个有错误的事务。
有两种处理方法:
通过始终按特定顺序锁定资源来避免死锁(例如,始终先更新帐号较小的帐户)。
遇到死锁时,您的代码必须重试事务。
与普遍看法相反,死锁不一定是错误。
我建议您阅读 PostgreSQL 文档中的 the chapter about concurrency control。
我是这方面的菜鸟,我所做的只是为一个用户连接到数据库,所以我不熟悉让多个用户访问数据库。
我的情况是:10 个设施将使用我的程序记录工人进出的时间,数据库将在主服务器上,而我在 programming/testing 该程序时所做的只是一个用户。我的问题是:多个远程位置是否可以使用一个用户连接数据库(应该不会发生冲突,因为他们都在写不同的东西,但在同一张表上)如果不是这样,我该怎么办?
好的关系数据库处理得很好,它是关系数据库中事务的所谓 ACID 属性中的“我”;它代表 隔离.
通过 locks 保护并发进程不会同时写入相同的 table 行,这会阻止其他事务,直到一个事务完成写入。
通过 multiversion concurrency control (MVCC) 保护读者免受并发写入,它保留旧版本的数据为读者服务,而不会阻塞任何人。
如果您将所有属于同一事务的数据修改包含在一个事务中,以便它们自动(ACID 中的“A”)发生,并且您的事务简单而简短,您的应用程序可能会正常工作。
如果不满足这些条件,可能会出现问题:
如果您的数据修改不受事务保护,则并发会话可能会看到不同会话的中间、不完整结果,从而处理不一致的数据。
如果您的交易很复杂,交易中后面的语句可能会以间接方式依赖前面语句的结果。这个假设可以被修改数据的并发 activity 打破。有以下三种方法:
悲观锁定:在您第一次使用它们时锁定所有数据
SELECT ... FOR UPDATE
这样在您的事务完成之前没有人可以修改它们。乐观锁定:不锁定,但每当您第二次访问数据时,检查是否没有其他人在此期间修改过它们。如果是这种情况,请回滚事务并重试。
使用像
REPEATABLE READ
和SERIALIZABLE
这样的高事务隔离级别,这可以更好地保证您正在使用的数据不会同时被修改。如果数据库不能保持保证,您必须准备好接收序列化错误,在这种情况下,您必须回滚事务并重试。
这些技术以不同的方式实现相同的目标。讨论何时使用哪个超出了这个答案的范围。
如果你的事务很复杂and/or需要很长时间(要尽可能避免长事务,因为它们会导致数据库中出现各种问题),你可能遇到 死锁,这是两个事务以一种“死拥抱”的方式相互锁定。 数据库将检测到这种情况并中断其中一个有错误的事务。
有两种处理方法:
通过始终按特定顺序锁定资源来避免死锁(例如,始终先更新帐号较小的帐户)。
遇到死锁时,您的代码必须重试事务。
与普遍看法相反,死锁不一定是错误。
我建议您阅读 PostgreSQL 文档中的 the chapter about concurrency control。