在SQL中,事务允许将多个操作(插入/更新/删除)组合成一个原子工作单位,可以完全执行或完全撤销。事务的生命周期基于以下命令:
BEGIN或START TRANSACTION — 开始事务;COMMIT — 确认更改;ROLLBACK — 撤销事务中的所有更改。SQL支持事务的隔离级别(未提交读、已提交读、可重复读、可串行化),这些级别决定了并行事务之间的数据可见性,并保护免受诸如“脏读”或“幻行”等问题影响。
为了控制数据的完整性,需要合理地:
SELECT ... FOR UPDATE)。PostgreSQL示例:
BEGIN; -- 获取并锁定产品行 SELECT * FROM inventory WHERE id = 1 FOR UPDATE; UPDATE inventory SET quantity = quantity - 1 WHERE id = 1; COMMIT;
流行数据库管理系统(PostgreSQL, MySQL)默认的隔离级别是什么?它与可串行化的有什么不同?
答案:
在PostgreSQL中,默认使用Read Committed隔离级别——在此级别下,事务只能看到请求时已提交的数据,但可能会出现“不可重复读”(non-repeatable reads)。
在MySQL(InnoDB)中,是Repeatable Read。与Serializable的区别在于,只有后者完全防止任何幻行或并行更改,但由于全局锁的原因,其性能明显较慢。
示例:
-- 在可重复读中,SELECT可以返回相同的行,而在已提交读中,在两个SELECT之间可能会出现新行。
历史
在大型金融系统中,在低隔离级别(已提交读)下进行大型账户转账时,偶尔出现同一余额被多个事务同时使用的情况。这导致了双重支出(竞争条件)。在切换到
Serializable并合理管理锁后,问题消失了。
历史
在电子商务中,未封装在事务中的
UPDATE product SET stock = stock - 1导致销售超过库存的商品。问题仅在大量竞争订单出现时显现。解决方案是使用事务和通过SELECT ... FOR UPDATE来锁定行。
历史
在物流系统中,某个表在频繁更新时忘记了显式提交。在故障的情况下,部分数据因自动提交或不正确的回滚而丢失。结果是记录丢失和代价高昂的审计。