批量更新方法会造成mysql死锁吗?

wangxi得 发布于 2016/07/20 09:55
阅读 1K+
收藏 0
public void batchUpdate(String tablename, final String[] val, final String[] obj, final List<Map> list) {
		StringBuffer sql = new StringBuffer("UPDATE " + tablename + " SET ");
		for(String value : val){
			sql.append(value + " = ?, ");
		}
		sql.deleteCharAt(sql.length()-2);
		sql.append(" WHERE ");
		for(int i=0; i<obj.length; i++){
			sql.append(obj[i] + " = ? ");
			if(i != obj.length -1){
				sql.append("AND ");
			}
		}
		logger.info(sql.toString());
		
		this.getJdbcTemplate().execute(sql.toString(), new PreparedStatementCallback() {

			@Override
			public Object doInPreparedStatement(PreparedStatement ps)
					throws SQLException, DataAccessException {
				// TODO Auto-generated method stub
				ps.getConnection().setAutoCommit(false);
				for(int i=0; i<list.size(); i++){
					int index = 1;
					for(String value:val){
						ps.setString(index, list.get(i).get(value).toString());
						index++;
					}
					for(String objVal : obj){
						ps.setString(index, list.get(i).get(objVal).toString());
						index++;
					}
					ps.addBatch();
				}
				Object o = ps.executeBatch();   
                ps.getConnection().commit();   
                ps.getConnection().setAutoCommit(true);
				return o;
			}
			
		});



以下是问题补充:

@wangxi得:om.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction (2016/07/20 09:57)
加载中
1
小王爷威武

这个代码,只要条件满足,肯定会死锁。

如果有2个线程同时做批量更新,

第一个线程更新了id=1的数据,

第二个线程更新了id=2的数据。

这个时候,第一个线程准备更新id=2的数据,但线程2所持连接未提交,无法取得数据库中该id=2的行锁。

同时第二个线程准备更新id=1的数据,也因为无法取得id=1的行锁,就造成了死锁。

解决办法的就是:如果更新条件的,比如说是主键,则根据主键排序之后批量做更新。

如果更新条件不是主键,可以那么单线程处理。

也可以通过单条语句执行来避免死锁。

不过,不使用批量性能太低了,你还是需要结合你的业务来调整代码避免死锁



wangxi得
wangxi得
已经找到原因了,更新主键即可,这个方法我觉得没有问题的
0
Mr_K
Mr_K
你这个是一条sql 语句,算不上批量更新吧···
0
sweeeeeet
sweeeeeet

- -好多槽点,,你可以去了解一下preparestatement,有类似executeBatch的方法,还有数据库事务,- -

wangxi得
wangxi得
什么问题?直接说啊
0
Gillian_Male
Gillian_Male
死锁的含义是你中有我我中有你,请体会
wangxi得
wangxi得
这话说的
返回顶部
顶部