您好,匿名用户
随意问技术百科期待您的加入

mysql innodb 并发插入问题,包大量死锁错误

0 投票

开了10个并发写线程,没1000条记录批量提交一次,结果mysql包大量死锁错误!
"Deadlock found when trying to get lock; try restarting transaction"

引擎用的是Innodb 主键字段是auto_increament.

mysql 有这么脆弱吗?

create table ASIA_ODDS( 
    id int NOT NULL AUTO_INCREMENT, 
    match_id INT DEFAULT 0, 
    match_bet007_id INT NOT NULL, 
    company_id SMALLINT NOT NULL ,	 
    first_pk DECIMAL(9,4) DEFAULT 0, 
    first_host_odds DECIMAL(9,4) DEFAULT 0, 
    first_guest_odds DECIMAL(9,4) DEFAULT 0, 
    pk DECIMAL(9,4) , 
    host_odds DECIMAL(9,4) DEFAULT 0, 
    guest_odds DECIMAL(9,4) DEFAULT 0, 
    is_end TINYINT DEFAULT 0, 
    is_zd TINYINT DEFAULT 0 , 
    changeState char(3) DEFAULT '000', 
    last_update_time timestamp , 
    PRIMARY KEY (id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我的测试java代码如下:

public class TestInsertAsiaOdds { 
    public static void main(String args[]) { 
        final long s = System.currentTimeMillis(); 
        CyclicBarrier latch = new CyclicBarrier(10, new Runnable() { 
            public void run() { 
                System.out.print("耗时:" + (System.currentTimeMillis() - s)); 
            } 
        }); 

        //10个线程并发插入500w条数据 
        List<Thread> lt = new ArrayList<Thread>(); 

        for (int i = 0; i < 10; i++) { 
            Thread t = new Thread(new Task(5000000, latch)); 
            lt.add(t); 
        } 

        //启动线程 
        for (Thread t : lt) { 
            t.start(); 
        } 
    } 

    private static class Task implements Runnable { 
        private int count; 
        private CyclicBarrier latch; 
        private String insSql = "insert into asia_odds2(match_id, match_bet007_id, company_id, first_pk, first_host_odds, first_guest_odds, pk, host_odds, guest_odds, is_end, is_zd, changeState) values(?,?,?,?,?,?,?,?,?,?,?,?)"; 
        
        public Task(int count, CyclicBarrier latch) { 
            this.count = count; this.latch = latch; 
        } 

        public void run() { 
            Connection conn = null; 
            PreparedStatement ps = null; 

            try { 
                conn = getConn(); //设为自动提交 
                conn.setAutoCommit(true); 
                ps = conn.prepareStatement(insSql); 

                for (int i = 0; i < count; i++) { 
                    ps.setInt(1, 1); 
                    ps.setInt(2, 2); 
                    ps.setInt(3, 3); 
                    ps.setDouble(4, 1.1); 
                    ps.setDouble(5, 1.1); 
                    ps.setDouble(6, 1.1); 
                    ps.setDouble(7, 1.1); 
                    ps.setDouble(8, 1.1); 
                    ps.setDouble(9, 1.1); 
                    ps.setInt(10, 0); 
                    ps.setInt(11, 0); 
                    ps.setString(12, "000");
                    ps.addBatch(); 

                    //1000一批提交一次 
                    if (i % 1000 == 0) { 
                        ps.executeBatch(); 
                        ps.clearBatch(); 
                    } 
                } 
                ps.executeBatch(); 
            } catch (Exception ex) { 
                ex.printStackTrace(); 
            } finally { 
                if (conn != null) { 
                    try { 
                        conn.close(); 
                    } catch (SQLException e) { 
                        e.printStackTrace(); 
                    } 
                } 
                try { 
                    latch.await(); 
                } catch (BrokenBarrierException e) { 
                    e.printStackTrace(); 
                } catch (Exception e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
}

运行一段时间后就会报:

java.sql.BatchUpdateException: Deadlock found when trying to get lock; try restarting >transaction at >com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1669) at >com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1085)
用户头像 提问 2012年 12月1日 @ Sejuani 上等兵 (427 威望)
分享到:

1个回答

0 投票

用 ps.executeBatch()的前提是cnn.setAutoCommit(false);等插入完毕只有再手工commit,

另外,第1000个数据的时候ps.executeBatch(); ps.clearBatch()也不是必须的

用户头像 回复 2012年 12月1日 @ 阿尔托莉雅 下士 (587 威望)
提一个问题:

相关问题

+2 投票
1 回复 79 阅读
0 投票
1 回复 41 阅读
0 投票
1 回复 35 阅读
用户头像 提问 2013年 11月10日 @ Redis 上等兵 (114 威望)
+3 投票
1 回复 72 阅读
用户头像 提问 2012年 12月1日 @ Zeus 上等兵 (193 威望)
0 投票
1 回复 22 阅读
用户头像 提问 2014年 2月10日 @ Varus 上等兵 (281 威望)

欢迎来到随意问技术百科, 这是一个面向专业开发者的IT问答网站,提供途径助开发者查找IT技术方案,解决程序bug和网站运维难题等。
温馨提示:本网站禁止用户发布与IT技术无关的、粗浅的、毫无意义的或者违法国家法规的等不合理内容,谢谢支持。

欢迎访问随意问技术百科,为了给您提供更好的服务,请及时反馈您的意见。
...