一种mysql jvm死锁

只读事务与普通读 work log 中假设了一种死锁,非mysql死锁,而是jvm死锁

CREATE TABLE `mytest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

LOCK TABLES `mytest` WRITE;
/*!40000 ALTER TABLE `mytest` DISABLE KEYS */;

INSERT INTO `mytest` (`id`, `name`)
VALUES
(1,'db');

 

public class JdbcUtilDeadLock {

private static final String URL_NO_TIMEZONE="jdbc:mysql://127.0.0.1:53306/mytest?useUnicode=true&characterEncoding=utf-8&useSSL=false";
private static final String USER="root";
private static final String PASSWORD="";

public static void main(String []f) {
select();
}

/**
* 这个不用开启事务
* @return
*/
public static List<Map<String,Object>> update() {
Connection conn = null;
List<Map<String,Object>> list = new ArrayList<>();
try{
conn = DriverManager.getConnection(URL_NO_TIMEZONE, USER, PASSWORD);
PreparedStatement pstmt = conn.prepareStatement("update mytest set `name` = 'db' where id = 1");
pstmt.executeUpdate();

} catch (Exception e){
e.printStackTrace();
}
return list;
}

/**
* 开启事务后 update阻塞
* @return
*/
public static List<Map<String,Object>> select() {
Connection conn = null;
ResultSet rs = null;
List<Map<String,Object>> list = new ArrayList<>();
try{
conn = DriverManager.getConnection(URL_NO_TIMEZONE, USER, PASSWORD);

conn.setAutoCommit(false);

/**
* 如果不开启事务,则不会死锁
*/
// conn.setAutoCommit(true);

PreparedStatement pstmt = conn.prepareStatement("select * from mytest where id = 1 for update");
rs = pstmt.executeQuery();
ResultSetMetaData md = rs.getMetaData(); //获得结果集结构信息,元数据
int columnCount = md.getColumnCount(); //获得列数

while (rs.next()) {
Map<String,Object> rowData = new HashMap<String,Object>();
for (int i = 1; i <= columnCount; i++) {
rowData.put(md.getColumnLabel(i), rs.getObject(i));
}
list.add(rowData);
}
/**
* 阻塞死锁
*/
update();

if(!conn.getAutoCommit())
conn.commit();

System.out.println(list);

} catch (Exception e){
e.printStackTrace();
try {
if(!conn.getAutoCommit())
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}

}
return list;
}
}

 

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
[{name=db, id=1}]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1086)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2834)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2441)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2366)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2350)
at jdbctimezone.JdbcUtilDeadLock.update(JdbcUtilDeadLock.java:32)
at jdbctimezone.JdbcUtilDeadLock.select(JdbcUtilDeadLock.java:73)
at jdbctimezone.JdbcUtilDeadLock.main(JdbcUtilDeadLock.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

 

阻塞时,使用jstack

"main" #1 prio=5 os_prio=31 tid=0x00007f962a800000 nid=0x1603 runnable [0x000070000ee89000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
- locked <0x0000000795f220b0> (a com.mysql.jdbc.util.ReadAheadInputStream)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3163)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3620)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3609)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4160)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2834)
- locked <0x0000000795f18b28> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156)
- locked <0x0000000795f18b28> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2441)
- locked <0x0000000795f18b28> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2366)
- locked <0x0000000795f18b28> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2350)
at jdbctimezone.JdbcUtilDeadLock.update(JdbcUtilDeadLock.java:32)
at jdbctimezone.JdbcUtilDeadLock.select(JdbcUtilDeadLock.java:73)
at jdbctimezone.JdbcUtilDeadLock.main(JdbcUtilDeadLock.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

 

posted on 2020-04-17 23:28  silyvin  阅读(566)  评论(0编辑  收藏  举报