PostgreSQL TRANSACTION(事务)详解
                           
天天向上
发布: 2025-03-12 23:45:25

原创
921 人浏览过

事务(Transaction)是一个逻辑上的工作单位,通常由多个 SQL 语句组成,事务确保在执行过程中所有的操作要么全部成功,要么全部失败,保证数据的一致性。PostgreSQL 提供了对事务的支持,确保在面对异常和错误时,数据库的完整性不被破坏。


1. 事务的四大特性:ACID

  • A – 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部不执行,不会处于部分完成的状态。
  • C – 一致性(Consistency):事务执行前后,数据库必须处于一致的状态。事务执行前后的约束、规则、触发器等不应被违反。
  • I – 隔离性(Isolation):并发执行的事务应该相互隔离,一个事务的执行不应受到其他事务的干扰。
  • D – 持久性(Durability):一旦事务提交,结果会永久保存在数据库中,即使系统崩溃也不丢失。

2. 基本事务操作

2.1 开始事务

事务通过 BEGINSTART TRANSACTION 命令开始。

BEGIN;
-- 或者
START TRANSACTION;

2.2 提交事务

COMMIT 用于提交当前事务,使事务中的所有操作成为永久改变。

COMMIT;

2.3 回滚事务

ROLLBACK 用于撤销当前事务中的所有操作,回滚后事务中所做的更改不会被保存。

ROLLBACK;

2.4 自动提交(Autocommit)

PostgreSQL 默认情况下在每条 SQL 语句执行后自动提交,即每次执行一个 SQL 命令时,它会被当作一个单独的事务。如果希望进行多个 SQL 操作作为一个事务执行,需要显式使用 BEGIN


3. 事务隔离级别

事务的隔离性决定了多个事务并发执行时,它们相互之间的干扰程度。PostgreSQL 支持四种标准的事务隔离级别:

3.1 READ UNCOMMITTED

允许事务读取未提交的数据,这可能导致“脏读”(Dirty Read),即一个事务读取另一个事务未提交的数据,可能会导致不一致的结果。

PostgreSQL 默认使用的隔离级别是 READ COMMITTED,而非 READ UNCOMMITTED,因为 READ UNCOMMITTED 不提供良好的数据一致性保证。

3.2 READ COMMITTED

事务只能读取已提交的数据。每次查询操作都会看到执行前已提交的数据,但查询过程中的数据可能会被其他事务修改,造成“不可重复读”(Non-repeatable Read)。

3.3 REPEATABLE READ

事务内的所有查询将返回相同的结果,即使其他事务修改了数据。避免了“不可重复读”的问题,但可能会发生“幻读”(Phantom Read)。

3.4 SERIALIZABLE

这是最强的隔离级别,事务执行时,相当于这些事务是串行执行的,避免了“脏读”、“不可重复读”和“幻读”。它保证了最高的数据一致性,但代价较大,性能较低。

3.5 设置事务隔离级别

可以在事务开始时设置隔离级别:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- 执行事务操作
COMMIT;

4. 并发控制

PostgreSQL 使用多版本并发控制(MVCC,Multi-Version Concurrency Control)来实现事务的隔离性,确保多个事务并发执行时能保证数据一致性。MVCC 允许每个事务有自己的数据版本,而不直接相互干扰。

4.1 锁机制

PostgreSQL 会在事务执行时对涉及的数据加锁,确保数据的正确性和一致性。不同的锁级别包括:

  • 行级锁:锁定单行数据,允许其他事务访问其他行。
  • 表级锁:锁定整个表,阻止其他事务对表的访问。

PostgreSQL 使用行级锁来避免锁冲突,这样可以提高并发性能。


5. 示例:事务操作

5.1 示例 1:开始、提交、回滚

-- 开始事务
BEGIN;

-- 执行一些操作
UPDATE employees SET salary = salary + 1000 WHERE department = 'HR';

-- 提交事务
COMMIT;

-- 或者,回滚事务
-- ROLLBACK;

5.2 示例 2:事务隔离级别设置

-- 设置事务隔离级别为 REPEATABLE READ
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 开始事务
BEGIN;

-- 执行操作
SELECT * FROM employees WHERE department = 'HR';

-- 提交事务
COMMIT;

5.3 示例 3:并发事务(模拟脏读)

-- 事务 1
BEGIN;
UPDATE employees SET salary = salary + 500 WHERE department = 'Engineering';

-- 事务 2(可能读取未提交的数据,产生脏读)
BEGIN;
SELECT * FROM employees WHERE department = 'Engineering';  -- 脏读

-- 提交事务 1
COMMIT;

-- 提交事务 2
COMMIT;

6. 事务管理的注意事项

  • 事务的使用应小心,避免长时间锁定资源:长时间运行的事务可能导致其他事务无法执行,影响并发性能。
  • 保证事务尽可能简短:将事务范围限定在必要的操作上,减少锁定的时间。
  • 避免脏读、不可重复读、幻读:根据业务需求选择合适的隔离级别,尽量保证数据一致性。
  • 回滚事务时要小心:避免在不必要时执行 ROLLBACK,因为它会撤销所有在事务中进行的操作。

7. 事务示例总结

-- 开始事务
BEGIN;

-- 执行一些数据库操作
UPDATE employees SET salary = salary + 1000 WHERE department = 'HR';

-- 提交事务
COMMIT;

-- 如果出错,回滚事务
-- ROLLBACK;

事务提供了对数据库操作的强大控制力,帮助确保数据的一致性和完整性。更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *