面试题答案
一键面试读已提交(Read Committed)
- 保证数据一致性方式:
- 每次执行语句时,PostgreSQL Zheap引擎会为每个查询生成一个新的快照。该快照包含了在查询开始时所有已提交的事务所做的修改。
- 读取数据时,只会看到已提交事务对数据的修改,未提交事务的修改对当前查询不可见。
- 关键实现机制:
- 利用多版本并发控制(MVCC)。每个数据行都有多个版本,通过事务ID(XID)标记版本的提交状态。当查询执行时,根据事务ID判断哪些版本是已提交的,从而读取正确的数据版本。
- 语句级别的快照隔离,每个SQL语句执行时获取的快照是独立的,所以不同语句看到的数据可能因为其他事务的提交而不同。
可重复读(Repeatable Read)
- 保证数据一致性方式:
- 在事务开始时,PostgreSQL Zheap引擎生成一个全局快照。在整个事务期间,所有的查询都基于这个初始快照。
- 这确保了在同一个事务内,多次读取相同数据时,看到的数据状态是一致的,不受其他并发事务提交的影响。
- 关键实现机制:
- 同样依赖MVCC。但与读已提交不同,事务内所有查询都使用事务开始时生成的快照,而不是每个语句生成新快照。
- 对于更新操作,会在事务提交时检查是否有其他事务修改了要更新的数据(通过比较快照中的数据版本和当前数据版本),如果有冲突则回滚事务。
串行化(Serializable)
- 保证数据一致性方式:
- 模拟事务串行执行的效果,确保并发执行的事务不会相互干扰,从而保证数据一致性。
- 每个事务在提交时,PostgreSQL Zheap引擎会检查是否与其他并发事务存在冲突。如果存在冲突,事务会被回滚。
- 关键实现机制:
- 基于MVCC和SI(Snapshot Isolation)机制,并增加了冲突检测和回滚机制。
- 在事务执行过程中,记录事务对数据的读写操作。在提交时,检查这些操作与其他并发事务的操作是否冲突(例如,一个事务写入的数据被另一个并发事务读取或写入)。如果有冲突,回滚当前事务。
- 采用一种叫做“谓词锁”的机制,在查询时锁定符合条件的数据范围,防止其他事务在该范围内进行修改,从而避免幻读等问题。
关键区别
- 快照生成时机:
- 读已提交在每个语句执行时生成快照;可重复读在事务开始时生成快照并在事务内使用;串行化基于事务开始时的快照,但提交时要进行更复杂的冲突检测。
- 并发控制粒度:
- 读已提交是语句级别的隔离,并发度较高,但可能导致同一事务内不同语句看到不同数据状态。
- 可重复读是事务级别的隔离,保证事务内数据一致性,但可能出现幻读。
- 串行化提供最高级别的隔离,完全模拟事务串行执行,杜绝幻读等问题,但并发度相对较低,因为可能频繁回滚冲突事务。
- 冲突检测与处理:
- 读已提交基本不涉及冲突检测(因为每个语句快照独立)。
- 可重复读在更新时检测数据版本冲突并回滚。
- 串行化在提交时对读写操作进行全面冲突检测,若有冲突则回滚事务。