跳至主要內容

事务与并发控制

bsfc.tech大约 3 分钟MySQL

事务(Transaction)和并发控制是数据库管理系统中非常重要的概念,它们确保了数据的完整性和一致性,特别是在多用户同时访问和修改数据的场景下。下面将详细解释这两个概念,并通过示例加以说明。

事务(Transaction)

事务是数据库操作的最小工作单元,它具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),这四个特性合称为ACID特性。

  • 原子性:事务被视为一个不可分割的整体,要么全部执行成功,要么全部失败,不会部分执行。
  • 一致性:事务执行前后,数据库的状态保持一致,即事务遵循所有的预定义规则,如账户余额不能为负。
  • 隔离性:多个事务并发执行时,一个事务内部的操作对其他事务是不可见的,仿佛其他事务不存在一样。
  • 持久性:一旦事务提交,其效果就会永久保存到数据库中,即使系统发生故障也不会丢失。

并发控制

当多个事务同时访问和修改相同的数据时,如果没有适当的控制,可能会导致数据不一致的问题,如脏读、不可重复读、幻读等。并发控制机制旨在解决这些问题,最常用的技术包括锁机制和事务隔离级别调整。

  • 锁机制:通过锁定数据项或表,阻止其他事务访问,主要有共享锁(读锁)和排他锁(写锁)。
  • 事务隔离级别:SQL标准定义了四种隔离级别,从低到高分别为:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)。不同的隔离级别提供了不同程度的并发访问控制和数据一致性保障。

示例

假设有一个银行账户表Accounts,包含字段AccountID, Balance

事务示例

START TRANSACTION;
-- 模拟转账操作
UPDATE Accounts SET Balance = Balance - 100 WHERE AccountID = 1;
UPDATE Accounts SET Balance = Balance + 100 WHERE AccountID = 2;
COMMIT;

这段代码演示了一个简单的转账事务,从账户1转出100元到账户2。如果任一步骤失败(如账户余额不足),整个事务都会回滚,保证了资金的准确转移。

并发控制示例

考虑两个事务并发执行,事务A试图从账户1转账100元到账户2,同时事务B查询账户1的余额。

  • 未设置隔离级别或设置为Read Uncommitted:事务B可能看到事务A尚未提交的更改(脏读)。
  • 设置为Read Committed:事务B只能看到事务A提交后的余额,避免了脏读,但可能出现不可重复读(事务B多次查询同一数据,结果可能不同)。
  • 设置为Repeatable Read(MySQL默认):事务B在开始后看到的数据不会因其他事务的提交而改变,避免了不可重复读,但可能遇到幻读(查询到事务A新增的记录)。
  • 设置为Serializable:最高隔离级别,通过串行化执行事务,彻底避免了并发问题,但性能代价较高。

使用事务隔离级别的示例(以MySQL为例):

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT Balance FROM Accounts WHERE AccountID = 1;
-- 执行其他操作...
COMMIT;

这个例子设置了事务的隔离级别为串行化,然后执行查询操作,确保了数据的一致性和可预测性,但请注意这会牺牲一定的并发性能。