这样多线程并发访问数据库会不会有问题?如果有如何解决?
本帖最后由 jilk89757 于 2013-05-21 18:03:23 编辑
最近有项目需要用多个数据库,我是将数据源放在一个map中保存的,每次应用获取连接时都去map中先拿到数据源,再获取连接。如果多线程并发取连接会不会有问题,求大神指点!说明:ComboPooledDataSource是c3p0一个简单连接池的应用
保存数据源
LinkedHashMap dbMap = new LinkedHashMap();
ComboPooledDataSource instance1 = new ComboPooledDataSource();
instance1.set...(..);//设置数据源参数
ComboPooledDataSource instance2 = new ComboPooledDataSource();
instance1.set...(..);//设置数据源参数
dbMap.put("instance1", instance1);//用dbMap保存多个数据源
dbMap.put("instance2", instance2);
获取数据库连接
public Connection getConnection(String dataSourceName) throws SQLException {
return dbMap.get(dataSourceName).getConnection();
}
------解决方案--------------------
不同意这个说法。楼主本来就是多个数据库,对应多个数据源。
dbMap.put(key, value)的时候,因为map里key的唯一性,不会存在并发问题。
这里应该是程序启动时执行一次就行了。
后面你获取session的地方,因为只是读,不涉及到修改,也不会存在问题。
------解决方案--------------------多线程并发的获取连接,如果存在获取相同的连接,即通过你的dbMap缓存对象并发的通过同一key得到相同的connection的话,则可能出现问题。
你这个有点像一个针对多个数据库的缓存的连接池吧,其实可以设计更好一点,可以对每一个connection设计一个超时的时长,如果超过例如5分钟没有使用,则断开连接,并从dbMap中移除掉,具体实现可以参考DelayQueue.java
------解决方案--------------------不好意思,没看清问题。如果是多个数据源只启动一次的话,而且数据源是只读的话,那段代码是没有问题的。
-------------------------------
我想关于C3P0自己封装好ComboDataSource获取Connection应该是线程安全的
-------------------------------
可以很明确地告诉你,Connection 不是线程安全的。JDBC 规范并没有强制要求 Connection 必须是线程安全的,因此 JDBC 驱动厂商不会将其实现为线程安全的。
C3P0 的数据源只是个连接池,只是在 JDBC 的 Connection 上做过一层包装而已,并不会去更改原始 Connection 的行为。
一般来说,基于 TCP 通信的实现的连接池都不会是线程安全的,JDBC 连接池也不例外。
你这个还有个问题,多个数据源用起来其实没有你想像得那么简单,最主要的问题在于多数据源的事务处理问题上。在 J2SE 环境中没法处理多数据源的分布式事务,一般只有在 J2EE 环境中使用 JTA 才能处理分布式事务,当然了,多数据源的分布式事务处理的性能也是很差的。
在 J2SE 环境中可以看一下 jOTM, jencks, SimpleJTA, atomikos 等框架。