面试题答案
一键面试1. 事务隔离性基础与Undo日志概述
PostgreSQL的Zheap引擎中,Undo日志主要用于撤销未提交事务对数据所做的修改,以确保事务的原子性和隔离性。事务隔离性要求每个事务在执行过程中,就好像是系统中唯一运行的事务一样,不受其他并发事务的干扰。
2. 多事务并发时Undo日志与并发控制的协同工作
- MVCC(多版本并发控制)机制:
- 版本生成:当一个事务对数据进行修改时,Zheap引擎会在Undo日志中记录旧版本的数据。新的数据版本被创建并与事务ID相关联。例如,事务T1更新某一行数据,旧版本数据被记录到Undo日志,新版本数据则带有T1的事务ID。
- 并发读取:在多事务并发执行时,读操作不会阻塞写操作,写操作也不会阻塞读操作。读取操作根据事务的可见性规则,从Undo日志和当前数据版本中获取合适的数据版本。如果一个事务T2读取数据,它会根据自身的事务ID和Undo日志中的事务ID来判断数据版本的可见性。如果T1未提交,T2将看不到T1所做的修改,而是读取旧版本数据,这个旧版本数据可能来自Undo日志。
- 锁机制辅助:
- 行级锁:在对数据行进行修改时,事务会获取行级排他锁(X锁)。例如事务T1要修改某一行数据,它会先获取该行的X锁。其他事务在T1释放锁之前无法获取相同行的排他锁或共享锁(S锁),避免了数据冲突。如果事务T2尝试获取该行的锁,会被阻塞,直到T1释放锁。
- 锁与Undo日志结合:当事务获取锁并修改数据时,Undo日志记录修改前的数据版本。如果事务因并发冲突(如死锁检测等情况)需要回滚,就可以利用Undo日志恢复数据到修改前的状态。例如,若检测到T1和T2形成死锁,选择其中一个事务(假设是T1)回滚,T1会根据Undo日志中的记录撤销对数据的修改,释放持有的锁,从而解除死锁。
3. 具体技术手段和流程
- 事务开始:事务启动时,系统为其分配一个唯一的事务ID(XID)。
- 数据修改:
- 事务获取数据行的锁(如X锁)。
- 在Undo日志中记录修改前的数据版本,包括旧的行数据以及相关元数据(如旧的事务ID等)。
- 修改数据行,更新相关的事务ID等元数据,标记新版本数据。
- 并发访问处理:
- 读操作:读取数据时,根据事务的可见性规则,判断是否从当前数据版本或Undo日志中获取数据。如果当前版本数据的事务ID未提交且大于当前事务的事务ID,则从Undo日志中读取旧版本数据。
- 写操作:获取锁失败的事务进入等待队列,直到锁可用。若等待过程中检测到死锁,选择一个事务进行回滚,利用Undo日志撤销该事务对数据的修改。
- 事务提交或回滚:
- 提交:事务提交时,释放持有的所有锁,系统将事务标记为已提交状态。此时,其他事务可以看到该事务对数据所做的修改。
- 回滚:事务回滚时,根据Undo日志中的记录,将数据恢复到修改前的状态,释放持有的锁,取消事务相关的所有操作。