Предотвращение тупиков (Java + MySQL) - PullRequest
0 голосов
/ 27 сентября 2011

У меня есть класс sql, который подключается к базе данных и обновляет информацию с моего игрового сервера.Мне было интересно, если что-нибудь здесь приведет к тупику и каковы хорошие способы предотвращения тупиков.Я новичок во многих вещах, поэтому любые советы будут отличными:)

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;
}
}

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Вам нужно беспокоиться о синхронизации на стороне Java, потому что реализации java.sql не являются поточно-ориентированными. И вам нужно подумать об изоляции на сервере базы данных, балансируя скорость отклика с ACID.

Я бы порекомендовал несколько других вещей для вашего класса Java:

  1. Использовать пул соединений. Разрушение и создание связей очень дорого. Ваш класс SQL не должен обрабатывать такие хлопоты.
  2. Используйте PreparedStatement и связывайте переменные. Создание строки запроса таким способом - плохая идея.
  3. Закрыть ресурсы в блоке finally.

Все эти статические строки ... Я читаю это на мобильном телефоне, но то, что я вижу, не очень хорошо. У вас может быть серьезное нарушение 1-й нормальной формы.

0 голосов
/ 27 сентября 2011

Взаимные блокировки обычно вызваны плохо синхронизированным кодом.Наиболее типичным случаем является то, что поток A получает блокировку для ресурса X, поток B получает блокировку для ресурса Y, а затем оба потока ждут, пока каждый из них попытается получить ресурс, который еще не заблокирован.

Поскольку в вашем коде вообще нет синхронизации, все должно быть в порядке.

Чтобы избежать проблем взаимоблокировки, постарайтесь выполнить минимальный объем работы внутри синхронизированных блоков.Будьте очень осторожны при вызове кода, внешнего для класса внутри синхронизированного блока, так как этот внешний код может попытаться получить блокировку и вызвать взаимоблокировку.Помните, что выполнение запроса к базе данных - это вызов внешнего кода, и для db-запроса нет ничего необычного в блокировке ресурсов внутри базы данных.

Вы действительно видите тупики или просто осторожны?

...