面试题答案
一键面试1. 锁定机制
- 节点和关系锁:Neo4j在事务执行过程中,会对涉及到的节点和关系加锁。例如,当一个事务要修改某个节点的属性时,它会获取该节点的独占锁。这样,其他并发事务在尝试修改同一节点时,就必须等待锁的释放。这有效防止了多个事务同时修改同一数据导致的数据不一致。比如,一个事务T1正在更新节点A的属性,此时另一个事务T2尝试更新节点A,T2就会被阻塞,直到T1提交或回滚事务并释放锁。
- 读写锁:Neo4j采用读写锁来管理对数据的读和写操作。读操作可以并发执行,因为它们不会修改数据,不会产生数据不一致问题。当有写操作时,会获取独占写锁,阻止其他读写操作,确保写操作的原子性和一致性。例如,多个事务可以同时读取节点数据,但如果一个事务要写入数据,就会独占该数据的锁,其他事务只能等待。
2. 原子性和持久性
- 原子性:Neo4j的事务具有原子性,即事务中的所有操作要么全部成功,要么全部失败。如果在事务执行过程中出现错误,例如某个Cypher查询执行失败,整个事务会回滚,所有已执行的操作都被撤销,数据恢复到事务开始前的状态。这保证了数据不会因为部分操作成功部分失败而处于不一致的状态。比如,一个事务包含创建节点、建立关系和更新节点属性三个操作,如果更新节点属性操作失败,前面创建节点和建立关系的操作也会被撤销。
- 持久性:一旦事务提交成功,其对数据库的修改就会持久化存储。Neo4j使用预写式日志(Write - Ahead Logging,WAL)来实现持久性。在事务执行过程中,所有的修改操作都会先记录到日志文件中。当事务提交时,日志会被持久化到磁盘,确保即使系统崩溃,已提交的事务数据不会丢失,从而保证了数据的一致性。例如,系统在事务提交后但还未将数据完全写入磁盘时崩溃,重启后可以根据WAL日志恢复已提交事务对数据的修改。
3. 多版本并发控制(MVCC)
- 版本号管理:Neo4j使用多版本并发控制机制,为每个数据对象维护多个版本。每个事务在开始时,会获得一个时间戳,这个时间戳决定了它能看到的数据版本。读操作不会阻塞写操作,写操作也不会阻塞读操作。例如,事务T1在时间戳t1开始,它看到的数据版本是t1时刻的数据状态。在T1执行过程中,事务T2对数据进行了修改并提交,生成了新的数据版本,但T1仍然看到的是t1时刻的版本,不受T2修改的影响。当T1提交时,它会检查数据版本,如果期间数据被其他事务修改,T1可能会失败并需要重新执行,以此保证数据的一致性。
- 快照隔离:MVCC机制实现了快照隔离,每个事务在开始时创建一个数据的快照。在事务执行过程中,读操作基于这个快照进行,所以不会看到其他并发事务未提交的修改。这避免了脏读问题,同时保证了并发事务之间的数据一致性。例如,事务T3读取数据时,基于它开始时创建的快照,即使此时有其他事务正在对数据进行修改,T3读取到的数据也是快照中的数据,不会受到未提交修改的干扰。
4. 一致性检查点
- 定期检查点:Neo4j会定期创建一致性检查点。在检查点过程中,数据库会将内存中的修改刷新到磁盘,并记录当前的事务日志位置。这确保了系统在崩溃后能够快速恢复到一个一致的状态。例如,当系统崩溃后重启,Neo4j可以从最近的检查点开始重放事务日志,快速恢复到崩溃前的状态,保证数据的一致性。
- 恢复机制:基于检查点和事务日志,Neo4j在恢复过程中可以识别出哪些事务已经提交,哪些事务未提交。对于已提交的事务,重新应用其修改;对于未提交的事务,撤销其部分完成的操作,从而保证数据库在重启后的数据一致性。例如,如果在检查点之后有两个事务T4和T5,T4已提交,T5未提交,重启时会重新应用T4的修改并撤销T5的操作。