2011-09-26 56 views
0

我有一个sql类,连接到数据库并更新来自我的游戏服务器的信息。我想知道这里是否有什么会导致僵局,以及防止死锁的好方法。我是新来的很多的东西,所以任何提示将是巨大的:)死锁预防(Java + MySQL)

package server.util; 

import java.sql.*; 
import java.security.MessageDigest; 

import server.model.players.Client; 

public class SQL { 

public static Connection con = null; 
public static Statement stmt; 
public static boolean connectionMade; 
public static void createConnection() { 
    try { 
     Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     con = DriverManager.getConnection("jdbc:mysql://URL/DATABASE", "USERNAME", "PASS"); 
     stmt = con.createStatement(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
public static ResultSet query(String s) throws SQLException { 
    try { 
     if (s.toLowerCase().startsWith("select")) { 
      ResultSet rs = stmt.executeQuery(s); 
      return rs; 
     } else { 
      stmt.executeUpdate(s); 
     } 
     return null; 
    } catch (Exception e) { 
     destroyConnection(); 
     createConnection(); 
     e.printStackTrace(); 
    } 
    return null; 
} 

public static void destroyConnection() { 
    try { 
     stmt.close(); 
     con.close(); 
     connectionMade = false; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public static boolean saveHighScore(Client clientToSave) { 
    try { 
     query("DELETE FROM `skills` WHERE playerName = '"+clientToSave.playerName+"';"); 
     query("DELETE FROM `skillsoverall` WHERE playerName = '"+clientToSave.playerName+"';"); 
     //query("DELETE FROM `scores` WHERE playerName = '"+clientToSave.playerName+"';"); 
     query("INSERT INTO `skills` (`playerName`,`Attacklvl`,`Attackxp`,`Defencelvl`,`Defencexp`,`Strengthlvl`,`Strengthxp`,`Hitpointslvl`,`Hitpointsxp`,`Rangelvl`,`Rangexp`,`Prayerlvl`,`Prayerxp`,`Magiclvl`,`Magicxp`,`Cookinglvl`,`Cookingxp`,`Woodcuttinglvl`,`Woodcuttingxp`,`Fletchinglvl`,`Fletchingxp`,`Fishinglvl`,`Fishingxp`,`Firemakinglvl`,`Firemakingxp`,`Craftinglvl`,`Craftingxp`,`Smithinglvl`,`Smithingxp`,`Mininglvl`,`Miningxp`,`Herblorelvl`,`Herblorexp`,`Agilitylvl`,`Agilityxp`,`Thievinglvl`,`Thievingxp`,`Slayerlvl`,`Slayerxp`,`Farminglvl`,`Farmingxp`,`Runecraftlvl`,`Runecraftxp`,`Hunterlvl`,`Hunterxp`,`Summonlvl`,`Summonxp`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.playerLevel[0]+","+clientToSave.playerXP[0]+","+clientToSave.playerLevel[1]+","+clientToSave.playerXP[1]+","+clientToSave.playerLevel[2]+","+clientToSave.playerXP[2]+","+clientToSave.playerLevel[3]+","+clientToSave.playerXP[3]+","+clientToSave.playerLevel[4]+","+clientToSave.playerXP[4]+","+clientToSave.playerLevel[5]+","+clientToSave.playerXP[5]+","+clientToSave.playerLevel[6]+","+clientToSave.playerXP[6]+","+clientToSave.playerLevel[7]+","+clientToSave.playerXP[7]+","+clientToSave.playerLevel[8]+","+clientToSave.playerXP[8]+","+clientToSave.playerLevel[9]+","+clientToSave.playerXP[9]+","+clientToSave.playerLevel[10]+","+clientToSave.playerXP[10]+","+clientToSave.playerLevel[11]+","+clientToSave.playerXP[11]+","+clientToSave.playerLevel[12]+","+clientToSave.playerXP[12]+","+clientToSave.playerLevel[13]+","+clientToSave.playerXP[13]+","+clientToSave.playerLevel[14]+","+clientToSave.playerXP[14]+","+clientToSave.playerLevel[15]+","+clientToSave.playerXP[15]+","+clientToSave.playerLevel[16]+","+clientToSave.playerXP[16]+","+clientToSave.playerLevel[17]+","+clientToSave.playerXP[17]+","+clientToSave.playerLevel[18]+","+clientToSave.playerXP[18]+","+clientToSave.playerLevel[19]+","+clientToSave.playerXP[19]+","+clientToSave.playerLevel[20]+","+clientToSave.playerXP[20]+","+clientToSave.playerLevel[21]+","+clientToSave.playerXP[21]+","+clientToSave.playerLevel[22]+","+clientToSave.playerXP[22]+");"); 
     query("INSERT INTO `skillsoverall` (`playerName`,`lvl`,`xp`) VALUES ('"+clientToSave.playerName+"',"+(clientToSave.getLevelForXP(clientToSave.playerXP[0]) + clientToSave.getLevelForXP(clientToSave.playerXP[1]) + clientToSave.getLevelForXP(clientToSave.playerXP[2]) + clientToSave.getLevelForXP(clientToSave.playerXP[3]) + clientToSave.getLevelForXP(clientToSave.playerXP[4]) + clientToSave.getLevelForXP(clientToSave.playerXP[5]) + clientToSave.getLevelForXP(clientToSave.playerXP[6]) + clientToSave.getLevelForXP(clientToSave.playerXP[7]) + clientToSave.getLevelForXP(clientToSave.playerXP[8]) + clientToSave.getLevelForXP(clientToSave.playerXP[9]) + clientToSave.getLevelForXP(clientToSave.playerXP[10]) + clientToSave.getLevelForXP(clientToSave.playerXP[11]) + clientToSave.getLevelForXP(clientToSave.playerXP[12]) + clientToSave.getLevelForXP(clientToSave.playerXP[13]) + clientToSave.getLevelForXP(clientToSave.playerXP[14]) + clientToSave.getLevelForXP(clientToSave.playerXP[15]) + clientToSave.getLevelForXP(clientToSave.playerXP[16]) + clientToSave.getLevelForXP(clientToSave.playerXP[17]) + clientToSave.getLevelForXP(clientToSave.playerXP[18]) + clientToSave.getLevelForXP(clientToSave.playerXP[19]) + clientToSave.getLevelForXP(clientToSave.playerXP[20]) + clientToSave.getLevelForXP(clientToSave.playerXP[21]) + clientToSave.getLevelForXP(clientToSave.playerXP[22]))+","+((clientToSave.playerXP[0]) + (clientToSave.playerXP[1]) + (clientToSave.playerXP[2]) + (clientToSave.playerXP[3]) + (clientToSave.playerXP[4]) + (clientToSave.playerXP[5]) + (clientToSave.playerXP[6]) + (clientToSave.playerXP[7]) + (clientToSave.playerXP[8]) + (clientToSave.playerXP[9]) + (clientToSave.playerXP[10]) + (clientToSave.playerXP[11]) + (clientToSave.playerXP[12]) + (clientToSave.playerXP[13]) + (clientToSave.playerXP[14]) + (clientToSave.playerXP[15]) + (clientToSave.playerXP[16]) + (clientToSave.playerXP[17]) + (clientToSave.playerXP[18]) + (clientToSave.playerXP[19]) + (clientToSave.playerXP[20]) + (clientToSave.playerXP[21]) + (clientToSave.playerXP[22]))+");"); 
     //query("INSERT INTO `scores` (`playerName`,`killcount`,`pkpoints`,`pcpoints`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.KC+","+clientToSave.pkPoints+","+clientToSave.pcPoints+");"); 
     } catch (Exception e) { 
     e.printStackTrace(); 
     return false; 
    } 
    return true; 
} 
} 
+1

它为什么是静态的?这是否有充分的理由?如果你不需要记住状态,你应该使用静态的东西。 – Ibolit

回答

2

你需要担心在Java端同步,因为java.sql中的实现是不是线程安全的。而且您需要考虑数据库服务器上的隔离,以平衡ACID的响应能力。

我推荐一些其他的东西对你的Java类:

  1. 使用连接池。破坏和创建连接非常昂贵。你的SQL类不应该处理这些杂事。
  2. 使用PreparedStatement并绑定变量。创建一个查询字符串是一个坏主意。
  3. 关闭finally块中的资源。

所有那些静态字符串...我正在手机上阅读此内容,但我所看到的并不好。你可能会严重违反第一范式。

0

死锁通常是由同步不佳的代码造成的。最典型的情况是,线程A获取资源X的锁,线程B获取资源Y的锁,然后两个线程都等待,而每个线程都试图获取它们尚未锁定的资源。

因为你的代码根本没有同步,所以应该没问题。

为了避免死锁问题,尽量在同步块内部尽可能少的工作量。对于在同步块内的类外部调用代码时要非常小心,因为此外部代码可能会尝试获取锁并产生死锁。请记住,执行数据库查询是对外部代码的调用,并且数据库查询锁定数据库内的资源并不罕见。

你实际上是否看到了僵局,还是你只是谨慎?

+0

许多人在他们的服务器中使用mysql来保存信息到数据库有死锁,我想知道如果MySQL造成它。比如,假设他们在用户登录时创建了他们的mysql连接,并且如果两个用户同时登录,会给出任何问题吗? – Aleksandr

+0

我不知道数据库中死锁的原因是否能够智能地回答。希望其他人可以跳进来帮助你。祝你好运。 –