gpt4 book ai didi

Java:使来自多个客户端的并发 MySQL 查询同步

转载 作者:行者123 更新时间:2023-11-29 01:46:52 25 4
gpt4 key购买 nike

我在一家游戏网吧工作,我们这里有一个系统 (smartlaunch),可以跟踪游戏许可证。我已经编写了一个与该系统接口(interface)的程序(实际上,它的后端 MySQL 数据库)。该程序旨在在客户端 PC 上运行,并且 (1) 查询数据库以从可用池中选择一个未使用的许可证,然后 (2) 将此许可证标记为由客户端 PC 使用。

问题是,我有一个并发错误。该程序旨在在多台机器上同时启动,当发生这种情况时,一些机器通常会尝试获取相同的许可证。我认为这是因为步骤 (1) 和 (2) 不同步,即一个程序确定许可证 #5 可用并选择它,但在它可以将 #5 标记为正在使用之前,另一台 PC 上的程序的另一个副本试图获取相同的许可证。

我试图通过使用事务和表锁定来解决这个问题,但似乎没有任何区别 - 我这样做对吗?下面是有问题的代码:

    public LicenseKey Acquire() throws SmartLaunchException, SQLException {
Connection conn = SmartLaunchDB.getConnection();
int PCID = SmartLaunchDB.getCurrentPCID();

conn.createStatement().execute("LOCK TABLE `licensekeys` WRITE");

String sql = "SELECT * FROM `licensekeys` WHERE `InUseByPC` = 0 AND LicenseSetupID = ? ORDER BY `ID` DESC LIMIT 1";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setInt(1, this.id);
ResultSet results = statement.executeQuery();

if (results.next()) {
int licenseID = results.getInt("ID");
sql = "UPDATE `licensekeys` SET `InUseByPC` = ? WHERE `ID` = ?";
statement = conn.prepareStatement(sql);
statement.setInt(1, PCID);
statement.setInt(2, licenseID);
statement.executeUpdate();
statement.close();
conn.commit();
conn.createStatement().execute("UNLOCK TABLES");
return new LicenseKey(results.getInt("ID"), this, results.getString("LicenseKey"), results.getInt("LicenseKeyType"));
} else {
throw new SmartLaunchException("All licenses of type " + this.name + "are in use");
}
}

最佳答案

你必须做两件事:

  • 将您的代码包装在事务中(以避免自动提交立即释放锁)
  • 使用 SELECT ... FOR UPDATE 和 mysql 会给你你需要的锁(提交时释放)

SELECT ... FOR UPDATE 优于 LOCK TABLE,因为它可能通过行级锁定来解决问题,而不是自动锁定整个表

关于Java:使来自多个客户端的并发 MySQL 查询同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4701791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com