简体   繁体   English

超过了锁定等待超时; 尝试使用spring和Mysql重新启动事务Java

[英]Lock wait timeout exceeded; try restarting transaction Java with spring and Mysql

In my application i am using spring with plain jdbc. 在我的应用程序中,我使用带有纯jdbc的spring。 and there are multiple thread that do various database operation.like checking if value does not exist in table then insert it. 并且有多个线程执行各种数据库操作。例如检查表中是否不存在值,然后将其插入。 Problem is i am getting exception >> Lock wait timeout exceeded; 问题是我正在获取异常>> 超出了锁定等待超时; try restarting transaction I have check in mysql SHOW ENGINE INNODB STATUS\\G; 尝试重新启动事务,我已经在mysql SHOW ENGINE INNODB STATUS \\ G中签入; and it gives desc 它给出了描述

------------
TRANSACTIONS
------------
Trx id counter D467
Purge done for trx's n:o < D459 undo n:o < 0
History list length 1050
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 64, OS thread handle 0xa6a0ab40, query id 9370 localhost root
SHOW ENGINE INNODB STATUS
---TRANSACTION D466, ACTIVE 22 sec
5 lock struct(s), heap size 320, 2 row lock(s), undo log entries 2
MySQL thread id 74, OS thread handle 0xa6c9eb40, query id 9369 localhost 127.0.0.1 root
Trx read view will not see trx with id >= D467, sees < D457
---TRANSACTION D464, ACTIVE 24 sec
5 lock struct(s), heap size 320, 2 row lock(s), undo log entries 2
MySQL thread id 70, OS thread handle 0xa6aceb40, query id 9354 localhost 127.0.0.1 root
Trx read view will not see trx with id >= D465, sees < D457
---TRANSACTION D462, ACTIVE 28 sec
2 lock struct(s), heap size 320, 1 row lock(s)
MySQL thread id 73, OS thread handle 0xa6c3cb40, query id 9347 localhost 127.0.0.1 root
Trx read view will not see trx with id >= D463, sees < D457
---TRANSACTION D45A, ACTIVE 87 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 34 lock struct(s), heap size 2496, 81 row lock(s), undo log entries 151
MySQL thread id 72, OS thread handle 0xa6a3bb40, query id 9054 localhost 127.0.0.1 root update
Insert into TABLE_1 ( ID,NAME,STATUS)values (44545,'temp','disable')
Trx read view will not see trx with id >= D45B, sees < D450
------- TRX HAS BEEN WAITING 26 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 159967 n bits 312 index `PRIMARY` of table `test2`.`TABLE_1` trx id D45A lock mode S locks rec but not gap waiting
Record lock, heap no 67 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 80016687; asc   f ;;
 1: len 6; hex 00000000d457; asc      W;;
 2: len 7; hex 2f0001dda310ee; asc /      ;;
 3: len 10; hex 4d6f68642e20417a697a; asc Mohd. Aziz;;
 4: SQL NULL;
 5: SQL NULL;
 6: len 1; hex 4d; asc M;;
 7: SQL NULL;
 8: len 1; hex 30; asc 0;;
 9: len 10; hex 496e646976696475616c; asc Individual;;
 10: len 6; hex 414354495645; asc ACTIVE;;
 11: len 4; hex 53a90e01; asc S   ;;

------------------
---TRANSACTION D457, ACTIVE 130 sec
77 lock struct(s), heap size 5504, 141 row lock(s), undo log entries 287
MySQL thread id 71, OS thread handle 0xa6affb40, query id 9001 localhost 127.0.0.1 root
Trx read view will not see trx with id >= D458, sees < D42E
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
 ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
2386 OS file reads, 1108 OS file writes, 155 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 884, seg size 886, 12 merges
merged operations:
 insert 102, delete mark 6, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 553253, node heap has 18 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG

I just understand from my research that mysql INNODB uses row level lock and for delete it aquires index lock (exclusive) and gap lock as shared. 我只是从我的研究中了解到,mysql INNODB使用行级锁,要删除它,需要共享索引锁(排他)和间隙锁。 and for some reason it wont release it. 由于某种原因,它不会释放它。 Then for some other insert in the same table it requires that lock.. and i get this excpetion. 然后在同一张桌子上的其他插入它需要那个锁..我得到了这个排他。 Can anyone suggest me how to resolve this issue? 谁能建议我如何解决此问题? Other required details >> 其他必需的详细信息>>

datasource.xml

<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
      <property name="url" value="jdbc:mysql://localhost:3306/test2" />
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="username" value="root" />
      <property name="password" value="root" />
      <property name="removeAbandoned" value="true" />
      <property name="initialSize" value="20" />
      <property name="maxActive" value="30" />
    </bean>

    <!-- Enable Annotation based Declarative Transaction Management -->
    <tx:annotation-driven proxy-target-class="true"
        transaction-manager="transactionManager" />

This is how i used plain jdbc with spring transaction >> 这就是我在春季交易中使用普通jdbc的方法>>

@Repository
@Transactional(rollbackFor=Exception.class)
public class StudentDaoImpl implements StudentDao {

private static final Logger log = Logger
        .getLogger(StudentDaoImpl.class);

@Autowired
private DataSource dataSource;

PreparedStatement stmt = null;
        ResultSet rs = null;
        int count = 0;
        String sql = "Select count(*) from SOMETABLE where ID= ?";
        Connection conn = null;
        try {
            conn = DataSourceUtils.getConnection(dataSource);
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, id);
            rs = stmt.executeQuery();

            while (rs.next()) {
                count = rs.getInt(1);
            }

        } catch (SQLException e) {
            e.printStackTrace();
            log.error(e);
            throw new Exception(e);
        } finally {
            close(stmt, rs);
            DataSourceUtils.releaseConnection(conn, dataSource);
        }
        return count;

} 

I would suggest JdbcTemplate, even if you mentioned learning curve. 即使您提到学习曲线,我也建议使用JdbcTemplate。 There isn't too much to learn and it's not difficult. 没有太多的东西要学习,也不难。 JdbcTemplate is taking away all of the boilerplate JDBC code: JdbcTemplate取消了所有样板JDBC代码:

@Repository
@Transactional(rollbackFor=Exception.class)
public class StudentDaoImpl implements StudentDao {

    private static final Logger log = Logger
        .getLogger(StudentDaoImpl.class);

    private final JdbcTemplate jdbcTemplate;

    private static final String COUNT_SOMETHING = "SELECT COUNT(*) "
        + "FROM SOMETABLE WHERE ID=?";

    @Autowired
    public StudentDaoImpl(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int countSomething() {
        return jdbcTemplate.queryForObject(COUNT_SOMETHING, Integer.class, 1);
    }
} 

Your problem resides in your database operations, it has nothing to do with the technology you use to access the database. 您的问题出在数据库操作上,与您用来访问数据库的技术无关。

The only reason why a database deadlock appears is that in some transactions/operations you lock the resources in the opposite order. 出现数据库死锁的唯一原因是,在某些事务/操作中,您以相反的顺序锁定资源。

For example: 例如:

Transaction 1: 交易1:

UPDATE table1 SET col=val WHERE id=1
DELETE FROM table2 WHERE id=2

Transaction 2: 交易2:

UPDATE table2 SET col=val WHERE id=2
UPDATE table1 SET col=val WHERE id=1

The first transaction acquires a lock to table1, row 1 . 第一个事务获取对table1第1行的锁定。 Meanwhile the second transaction gets a lock to table2, row 2 . 同时,第二个事务锁定到table2第2行

Then, the first transaction wants to get the row 2 from table2 , but cannot, because the second transaction already has it. 然后,第一个事务想要从table2中获取行2 ,但是不能,因为第二个事务已经拥有它。 So, tr1 has to wait. 因此,tr1必须等待。

Similarly, tr2 has to wait, too, because it wants to get row 1 from table1 , but tr1 holds it. 同样,tr2也必须等待,因为它想从table1中获取行1 ,但是tr1保留了它。 So, they are waiting for each other, and only a timeout can release (and roll back) one of the transactions (the other one can run, if it has enough time remaining). 因此,他们彼此等待,只有超时可以释放(并回滚)其中一个事务(如果剩余时间足够,则另一个可以运行)。

The solution: 解决方案:

You give priorities to your tables, and ALWAYS use them in that order (eg table1 , table2 ). 您将优先级赋予表,并始终按该顺序使用它们(例如table1table2 )。 If your logic dictates that you need some data from table2 first, you can think on reversing the order OR put a lock on the smallest possible set of rows in table1 that will surely cover the rows involved in the final operation (it may be that you have to lock all rows in table1 , or put a table-level lock instead). 如果您的逻辑指示您首先需要从table2中获取一些数据,则可以考虑颠倒顺序,或者将锁锁定在table1中最小的可能行集合中,这肯定会覆盖最终操作中涉及的行(可能是您必须锁定table1中的所有行,或者放置表级锁定)。

And yes, ALL operation, including GUI queries, background processes, reports, etc. MUST use the same order. 是的,所有操作(包括GUI查询,后台进程,报告等)都必须使用相同的顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MySQL错误:超过了锁定等待超时; 尝试重新启动事务查询 - MySQL Error: Lock wait timeout exceeded; try restarting transaction Query 超过了锁定等待超时; 尝试在spring_Hibernate_Mysql中重新启动事务 - Lock wait timeout exceeded; try restarting transaction in spring_Hibernate_Mysql java.sql.SQLException:超出了锁定等待超时; 尝试重新启动事务异常在MYSQL中发生 - java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction exception occur in MYSQL 由于“超过了锁定等待超时,导致事务失败; 尝试重新开始交易” - Transactions fails due to “Lock wait timeout exceeded; try restarting transaction” 超过锁定等待超时; 尝试使用JDBC重新启动事务 - Lock wait timeout exceeded; try restarting transaction using JDBC 如何修复 Mysql 表之前工作时的“超出锁定等待超时;尝试重新启动事务”? - How to fix "Lock wait timeout exceeded; try restarting transaction" for Mysql table when it was working before? 发出java.lang.Exception:超出了锁定等待超时; 尝试重新启动事务 - Issue java.lang.Exception: Lock wait timeout exceeded; try restarting transaction 获取WARN:SQL错误:1205,SQLState:41000错误:超出锁定等待超时; 尝试重新启动事务。 使用休眠保存记录 - Getting WARN: SQL Error: 1205, SQLState: 41000 ERROR: Lock wait timeout exceeded; try restarting transaction. Saving a record in using hibernate 由于挂起事务 FK 插入,Mysql 事务获得“超出锁定等待超时” - Mysql transaction getting 'Lock wait timeout exceeded' because of pending transaction FK insert 无法获取锁定异常:锁定等待超时超过Spring SQL - Cannot aquire lock exception: lock wait timeout exceeded spring sql
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM