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解决办法

nexus3.1 迁移之后,启动报错“Lock file access denied”解决办法

9. Lock wait timeout exceeded