之前关于事物一章,由于当时的环境不方便测试所以跳过去了,现在回过头来,这一章一定要了解下,因为Neo4j是支持ACID的,示例项目采用上一章建的项目neo4j_sample下的springboot_sdn_embedded,使用Neo4j核心API演示。
事物声明方式
在没有引入Spring之前,事物采用如下原始的方式声明,引入Spring之后只需要@Transactional,这个相信大家都懂。
另外有一点要注意下,如果在Neo4j中做任意与模式相关的操作(创建模式索引),需要在一个单独的事物中,否则会抛出异常。
事物隔离级别
下面先代码测试下看看Neo4j默认的事物隔离级别是什么样的
|
|
|
|
IDEA中同时调试两个线程
随便选择一个红色断点右击,会弹出一个对话框,选择将All改成Thread,并设置成默认,这样调试的时候,在Debugger标签页就能选择对应的线程debug。
浏览器开两个窗口先后请求localhost:8080/threadA和localhost:8080/threadB,首先断点都停在了controller,然后按照顺序选择对应的线程debug。我debug的顺序在TransactionService注释中已经标明,输出结果依次为30、30、35、30、35,所以最终可以得出结论,threadA可以读到threadB已经提交过的修改,也就是说和传统关系型数据库的READ COMMITTED隔离级别相似。
更高级别的锁控制
Neo4j的事物是由清晰的读锁和写锁来控制每一个图形数据库资源的,下面我们看下如何手动控制锁
跟之前一样的方式调试下,在readLock()方法中通过tx.acquireReadLock(john),获取了john节点的读锁,然后再跑writeWaitReadLock(),当跑到步骤3的setProperty方法时会进入等待,此时再跑完readLock()线程,事物提交了,读锁也自动释放了,writeWaitReadLock()线程会立刻被激活,然后顺利完成自己的事物。输出结果依次为35、35、35、38,正常。