面试题答案
一键面试检测和防止写偏序异常的手段
- 事务时间戳:
- 在PostgreSQL的SSI(Serializable Snapshot Isolation)中,每个事务都被分配一个唯一的时间戳。时间戳是事务启动时生成的,这个时间戳在整个事务生命周期内保持不变。
- 当一个事务进行写操作时,它的时间戳用于确定写操作的顺序。如果有多个事务并发地尝试对同一数据进行写操作,时间戳较小的事务会先被处理,从而避免写偏序异常。
- 事务状态跟踪:
- PostgreSQL维护事务的状态信息,包括事务是否已提交、正在进行或已中止。
- 对于读操作,系统需要知道哪些事务在读取操作开始后启动(这些事务的写操作可能会影响读操作的结果)。通过跟踪事务状态,当一个读事务发现有较新的写事务可能影响其读取的数据时,就可以采取相应措施来防止写偏序异常。
- 谓词锁:
- 当一个事务进行写操作时,它会对写操作涉及的数据行或数据范围设置谓词锁。谓词锁与传统的行级锁不同,它是基于数据的逻辑条件(谓词)设置的。
- 例如,如果一个事务要更新满足某一条件(如
WHERE column > 10
)的所有行,它会设置一个基于这个条件的谓词锁。其他事务在进行读或写操作时,会检查是否与这些谓词锁冲突。如果冲突,就可能导致读事务回滚或等待,以防止写偏序异常。
事务处理流程
- 读事务流程:
- 启动事务:读事务开始时,被分配一个时间戳。
- 读取数据:读事务从数据库中读取数据。此时,系统会根据事务的时间戳和其他事务的状态来确定读取的一致性视图。读事务只会看到在其启动时间戳之前已提交的事务的修改。
- 结束事务:读事务完成读取操作后,通常以提交事务结束。由于读事务不进行写操作,一般不会导致写偏序异常,但如果在读取过程中检测到与较新写事务的潜在冲突(例如通过谓词锁检查),读事务可能会被回滚。
- 写事务流程:
- 启动事务:写事务开始时,同样被分配一个时间戳。
- 写操作:写事务对数据进行修改,并设置谓词锁。在写操作过程中,系统会检查是否与其他事务的谓词锁冲突。如果有冲突,可能需要等待或回滚事务。
- 提交事务:在写事务准备提交时,系统再次检查是否存在写偏序异常。它会对比自己的时间戳与其他相关事务的时间戳和状态。如果发现有较新的事务可能导致写偏序(例如,有较新的读事务读取了写事务修改前的数据,且写事务的修改可能影响读事务的一致性视图),写事务会被回滚。只有在确认不存在写偏序异常后,写事务才能成功提交,将修改持久化到数据库中。