import java.sql.*; public class Main { public static void main(String[] args) throws Exception { Class.forName("org.sqlite.JDBC"); Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db"); Statement stat = conn.createStatement(); stat.executeUpdate("drop table if exists people"); stat.executeUpdate("create table people (name,occupation)"); conn.close(); sqlTask tasks[] = { new sqlTask("Gandhi","politics"),new sqlTask("Turing","computers"),new sqlTask("Picaso","artist"),new sqlTask("shakespeare","writer"),new sqlTask("tesla","inventor"),}; System.out.println("Sequential DB access:"); Thread threads[] = new Thread[tasks.length]; for(int i = 0; i < tasks.length; i++) threads[i] = new Thread(tasks[i]); for(int i = 0; i < tasks.length; i++) { threads[i].start(); threads[i].join(); } System.out.println("Concurrent DB access:"); for(int i = 0; i < tasks.length; i++) threads[i] = new Thread(tasks[i]); for(int i = 0; i < tasks.length; i++) threads[i].start(); for(int i = 0; i < tasks.length; i++) threads[i].join(); } private static class sqlTask implements Runnable { String name,occupation; public sqlTask(String name,String occupation) { this.name = name; this.occupation = occupation; } public void run() { Connection conn = null; PreparedStatement prep = null; long startTime = System.currentTimeMillis(); try { try { conn = DriverManager.getConnection("jdbc:sqlite:test.db"); prep = conn.prepareStatement("insert into people values (?,?)"); prep.setString(1,name); prep.setString(2,occupation); prep.executeUpdate(); long duration = System.currentTimeMillis() - startTime; System.out.println(" sql Insert completed: " + duration); } finally { if (prep != null) prep.close(); if (conn != null) conn.close(); } } catch(sqlException e) { long duration = System.currentTimeMillis() - startTime; System.out.print(" sql Insert Failed: " + duration); System.out.println(" sqlException: " + e); } } } }
[java] Sequential DB access: [java] sql Insert completed: 132 [java] sql Insert completed: 133 [java] sql Insert completed: 151 [java] sql Insert completed: 134 [java] sql Insert completed: 125 [java] Concurrent DB access: [java] sql Insert completed: 116 [java] sql Insert completed: 1117 [java] sql Insert completed: 2119 [java] sql Insert Failed: 3001 sqlException: java.sql.sqlException: database locked [java] sql Insert completed: 3136
顺序插入5条记录大约需要750毫秒,我期望并发插入大概花费相同的时间。但是你可以看到给定3秒的超时时间,甚至没有完成。我也在C中编写了一个类似的测试程序,使用sqlite的本机库调用,并在大部分同时插入的时候完成了同时插入。所以问题是我的java库。
这是运行C版本时的输出:
Sequential DB access: sql Insert completed: 126 milliseconds sql Insert completed: 126 milliseconds sql Insert completed: 126 milliseconds sql Insert completed: 125 milliseconds sql Insert completed: 126 milliseconds Concurrent DB access: sql Insert completed: 117 milliseconds sql Insert completed: 294 milliseconds sql Insert completed: 461 milliseconds sql Insert completed: 662 milliseconds sql Insert completed: 862 milliseconds
我尝试使用两个不同的JDBC驱动程序(http://www.zentus.com/sqlitejdbc和http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC)和sqlite4java包装器。每次结果相似。有没有人知道没有这种行为的java的sqlite库?
另外,sqlite不支持每行锁定(还有?)。基本上每个操作的整个数据库文件变为locked。如果您幸运,并且文件系统支持字节范围锁定,则多个读卡器可能会同时访问您的数据库,但您不应该假定这种行为。
核心sqlite库by default allows multiple threads to use the same connection concurrently没有问题。我认为任何理智的JDBC包装器也将允许Java程序中的行为,尽管我还没有实际尝试过。
所以你有两个解决方案:
>在所有线程之间共享相同的JDBC连接。
>由于sqlite开发人员似乎认为是threads are evil,你最好是有一个线程处理所有的数据库操作,并使用Java代码自行序列化DB任务…
您可能想看看this old question of mine – 似乎已经累积了几个提示,以提高sqlite中的更新性能。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。