JDBC 迁移数据报: Lock wait timeout exceeded; try restarting transaction 的解决办法
Posted 袁义锐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC 迁移数据报: Lock wait timeout exceeded; try restarting transaction 的解决办法相关的知识,希望对你有一定的参考价值。
系统偶然爆出 Lock wait timeout exceeded; try restarting transaction 的错误,网上都是杀进程的方式;JDBC没有解决办法了都。
问题产生的原因是没有给JDBC的connect设置隔离;今天非常偶然在笔记中找到一句话:
如果是使用JDBC对数据库的事务设置隔离级别的话,也应该是在调用Connection对象的setAutoCommit(false)方法之前。
调用Connection对象的setTransactionIsolation(level)即可设置当前链接的隔离级别,至于参数level,可以使用Connection对象的字段:
后记:隔离级别的设置只对当前链接有效。对于使用mysql命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;
对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。
问题解决代码:
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
如何mock,复现问题:
在navicat客户端中,执行如下SQL开启事务,就是不提交;然后启动代码update语句,模拟多个事务交叉的情况;
start transaction;
update table_name set desc = '123' where id = '2';
笔记内容:
事务的特性:
1.原子性:操作是不可分割的
2.持久性:事务一旦提交,数据永久保存
3.隔离性:事务和事务之间不会彼此干扰
4.一致性:事务执行前后要一致;
1.不可重复读:相同的请求每次查询结果不一样;原因是A事务提交后,B修改了A事务提交的内容,而A一直读不到相同的结果
2.幻读:A事务提交后,查询结果不一致
3.脏读:事务读取了别的事务还未提交的数据
为了避免以上问题,MySQL数据库为我们提供的四种隔离级别:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。 -- ----mysq 默认的隔离级别,如InnoDB的设计思路,行级别的读写锁;
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
执行的效率是从低到高的;
在MySQL数据库中,支持上面四种隔离级别,【默认】的为Repeatable read (可重复读);
在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中【默认】的为Read committed级别
记住:设置数据库的隔离级别一定要是在开启事务之前!
如果是使用JDBC对数据库的事务设置隔离级别的话,也应该是在调用Connection对象的setAutoCommit(false)方法之前。
调用Connection对象的setTransactionIsolation(level)即可设置当前链接的隔离级别,至于参数level,可以使用Connection对象的字段:
后记:隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;
对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。
public void moveHiveMetaData(List<Map<String, String>> list)
Connection connection = null;
PreparedStatement statement = null;
try
connection = jdbcUtil.getConnection();
//一定要在setAutoCommit之前
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// 设置false,开启jdbc事务
connection.setAutoCommit(false);
statement = connection.prepareStatement("" + "insert into \\n" + "meta_db(db_name)\\n" + "values(?) \\n" + "ON DUPLICATE KEY UPDATE;");
long start = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++)
Map<String, String> map = list.get(i);
statement.setString(1, map.get("NAME"));
statement.addBatch();
statement.executeBatch();
connection.commit();
long end = System.currentTimeMillis();
logger.info("move data spend time ", (end - start));
catch (SQLException s)
logger.info("move data fail", s);
finally
jdbcUtil.close(statement, connection);
以上是关于JDBC 迁移数据报: Lock wait timeout exceeded; try restarting transaction 的解决办法的主要内容,如果未能解决你的问题,请参考以下文章
在mysql数据库中为啥经常报错:lock wait timeout exceeded,是啥原因引起的?该如何解决?
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try r
mysql执行insert等语句报1205 Lock wait timeout exceeded try restarting transaction
mysql提示 Lock wait timeout exceeded解决办法