我现在遇到的问题是同时处理SQL UPDATE
和DELETE
语句。如果程序只是一个接一个地调用,则没有问题,但是,如果两个人决定运行程序,它可能会失败。
我的计划的作用:
关于食物的程序,其中都有描述和描述时间的日期。当人们输入食物的描述时,它会被输入数据库,您可以在其中快速检索描述。如果描述是让我们说7天,那么我们delete
会导致它过时。但是,如果用户使用不同的描述输入数据库中已有的食物,则我们update
并更改日期。删除发生在更新/插入之后(那些不需要更新的插入将被插入,然后程序检查数据库中过时的东西并删除它们。)
问题:
当一个人正在尝试更新食物时,有两个人正在运行该程序,另一个人正在尝试更新食物,另一个人将其删除,因为它刚刚完成。更新不会发生,程序将继续进行其余更新(< - 我读到这是因为我的驱动程序没有停止。如果出现错误,某些驱动程序会停止更新。)
我想做什么:
我希望我的程序停止更新错误或抓住食物位置并重新启动进程/线程。重新启动将包括挑选出需要更新或插入的食物。因此,坏记录将被移动到插入方法而不是更新。更新将在中断的地方继续。一切都很好。
我知道这不是唯一的方法,所以欢迎不同的方法来解决这个问题。我已经查询过您可以使用upsert
语句,但也有竞争条件。 (关于upsert
声明的问题:如果我使upsert
方法同步,那么它是否没有竞争条件?)
由于
答案 0 :(得分:1)
在java代码中将事务级别设置为可序列化。然后你的陈述应该是这样的:
update food_table set update_time = ? where ....
delete from food_table where update_time < ?
在任何一种情况下,您都可能获得可序列化的异常。在更新的情况下,您将需要重新插入条目。在第二种情况下,只需忽略并再次运行。
答案 1 :(得分:1)
根据jout jdbc连接管理,您的问题有不同的实用解决方案。
如果应用程序是客户端服务器,并且它使用专用的持久连接(即它在程序启动时打开jdbc连接,并在程序关闭时关闭),则可以使用select for update
语句。
在向用户显示记录时,必须发出select for update,当用户执行其操作时,您执行所需的操作并提交。
此方法序列化数据库操作,如果您显示并锁定多个记录,则可能不可行。
如果您的Web应用程序具有连接池,或者您没有可用于读取和更新/删除操作的专用连接,则可以使用第二种方法。在这种情况下,您有这种情况
用户1使用jdbc connection 1
选择其数据用户2使用jdbc connection 2
选择其数据(与用户1相同)用户2使用jdbc连接3提交导致一些删除的数据
用户1提交数据并批量更新,因为数据已使用jdbc connection 2删除
由于您无法依靠相同的jdbc连接来锁定您读取的数据,因此您可以在更新数据之前发出select for update
并检查是否有数据。如果你有数据,你可以更新它们(并且它们不会被其他会话删除,因为对同一数据的每个删除命令都在等待你的select更新终止);如果您没有数据,因为在用户显示期间删除了数据,则必须重新插入数据。删除语句必须在日期列上具有表示上次更新的过滤器。
您可以使用其他方法,并使用例如
来避免选择更新 update food-table set last_update=? where id=? and last_update=<the last update you have in java program>
并且您必须检查update语句是否确实更新了一行(在jdbc中,executeUpdate返回修改的行数,但是您没有指定是否使用“普通”JDBC或某种框架)并且如果它没有更新一行必须是插入语句。