Spring事务及其与synchronized关键字的交互
我有一个 DAO 类,它使用 Spring JDBC 访问 SQLite 数据库。我已经在 DAO 方法本身上声明了事务,因为我的服务层从不将查询组合到事务中。
由于我并行使用几个工作线程,但只有一个线程可以同时更新 SQLite DB,因此我使用 synchronized
来序列化对 DAO 的访问。
首先,我从服务类进行外部同步,例如:
synchronized (dao) {
dao.update(...);
}
然后,我想我不妨摆脱外部同步,并将 synchronized
放在 DAO 方法本身上:
public synchronized void update(...) {
// Spring JDBC calls here
}
奇怪的是:我的现在查询所需的时间是以前的两倍!
为什么?
I have a DAO class that uses Spring JDBC to access an SQLite database. I have declared transactions on the DAO methods themselves since my service layer never combines queries in a transaction.
Since I use a few worker threads in parallel but only one thread can update an SQLite DB at the same time, I use synchronized
to serialize access to the DAO.
At first, I synchronized externally from my service class, for example:
synchronized (dao) {
dao.update(...);
}
Then, I figured I might as well get rid of the external synchronization and put synchronized
on the DAO method itself:
public synchronized void update(...) {
// Spring JDBC calls here
}
The strange thing is: my queries now take twice the time they used to!
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,有一个区别是显而易见的:
这一点的含义取决于您的其他代码,但这就是明显的区别。
Well, one difference is obvious:
What the implications of this are depends on your other code, but that's the obvious difference.
我的猜测是您的更新方法或整个类都用事务注释或通过其他方式由事务代理包装。这意味着每当您调用 dao 的方法时,事务代理都会从池中检索数据库连接,打开一个事务,然后调用真正的方法。
在第一个场景中,您甚至在到达代理之前就进行了同步,因此不会发生连接和事务魔法。在第二种情况下,您在此之后进行等待呼叫。
如果有多个线程尝试同时执行更新,则只有一个线程执行更新,其余线程将首先打开新连接,然后等待 dao 访问。因此,您将使用多个连接,而不是不断地重复使用一个连接。我只能猜测这对性能有何影响,但您可以从一个开始尝试不同的池大小。
My guess is your update method or entire class is annotated with Transactional or wrapped by transactional proxy through other means. This means whenever you call dao's method, the transactional proxy retrieves db connection from the pool, opens a transaction and then calls the real method.
In your first scenario you synchronize before even reaching the proxy, thus no connection and transaction magic happens. In the second scenario you do the waiting call after that.
If there are multiple threads trying to perform simultaneous updates there will be only one doing the update and the rest will be first opening new connections and then waiting for dao access. As a consequence instead of one connection being constantly reused you will have multiple connections in use. I can only guess how this really affects the performance but you can experiment with different pool size starting with one.