简体   繁体   English

如何在Java中实现ACID事务?

[英]How to implement ACID Transaction in Java?

I have to perform 2 actions, one to save data in db, one to save bytes on filesystem, and I would like these 2 actions to be executed atomically. 我必须执行2个动作,一个将数据保存到db中,一个将字节保存在文件系统上,我希望这2个动作可以原子执行。 Basically, if action 1 fails, the whole process fails, and if action 2 fails, same thing and db action is rollbacked. 基本上,如果操作1失败,则整个过程将失败,如果操作2失败,则将回滚同一件事和db操作。

public void doAction() {
   this.saveData();
   this.saveFile();
}

How is it possible to perform ACID transaction which involves database and filesystem in Java ? 如何执行Java中涉及数据库和文件系统的ACID事务?

In general this is just impossible. 总的来说,这是不可能的。

File systems are not a transactional resource (unless you're consciously and deliberately on a journaled filesystem or so) and even if they were there would still be the requirement that they can engage in a 2PC transaction, together with the db transaction, under an "external" transaction controller (who can steer and control the two-phase-commit process that will be required). 文件系统不是事务性资源(除非您有意识地和有意地使用日志文件系统),即使它们存在,仍要求它们可以在数据库环境下与db事务一起参与2PC事务。 “外部”事务控制器(可以控制和控制所需的两阶段提交过程)。 Your chances are slim. 您的机会很小。

You can try to do all sorts of thing yourself, eg keep a log of the pre-write state of any file (or file portions) written to, but basically you are then recreating a journaled file system yourself and unless you do so fully and completely (not an easy task), your system will still have (serious) holes in it. 您可以尝试自己做各种事情,例如,记录写入的任何文件(或文件部分)的预写状态日志,但是基本上,您将自己重新创建日志文件系统,除非您完全这样做并且完全(这不是一件容易的事),您的系统中仍然会有(严重)漏洞。

ACID requires not only to be able to rollback changes when one of the operations fail, it also requires isolation from other transaction. ACID不仅要求在其中一项操作失败时能够回滚更改 ,还要求与其他事务隔离 As soon as you store data to a file, changes get visible to others. 一旦将数据存储到文件中,其他人就可以看到更改。 Either committing the database before or after is a violation of the ACID rules. 在此之前或之后提交数据库都违反了ACID规则。

However, you may still find a solution for the actual problem you have to solve. 但是,您仍然可以找到必须解决的实际问题的解决方案。 Eg by synchronizing file access with database data (store file names and whether data is ready, for instance). 例如,通过将文件访问与数据库数据同步(例如,存储文件名以及数据是否准备就绪)。

Also consider storing the data in a blob instead of a file. 还可以考虑将数据存储在Blob中而不是文件中。

Another more complicated way is to lock access to the data by the file system, so when a transaction is writing, all others are blocked from reading and writing of the file and the corresponding database data at the same time. 另一个更复杂的方法是锁定文件系统对数据的访问,因此在写入事务时,将阻止所有其他事务同时读取和写入文件以及相应的数据库数据 Eg Use an empty lock file (original-filename.lock) that blocks others from reading / writing the data in that file. 例如,使用一个空的锁定文件(original-filename.lock),该文件将阻止他人读取/写入该文件中的数据。 This only works if you have a 1-to-1 relation to database data and if you don't do any complex querying (you should not read the data while it is locked). 仅当您与数据库数据具有1对1的关系并且不执行任何复杂的查询(锁定数据时,不应读取数据)时,此方法才有效。 And of course it only works if you have control over everything that accesses the file or the database. 当然,只有在您可以控制访问文件或数据库的所有内容时,它才有效。 It may not be very efficient. 它可能不是很有效。 You still need to implement a rollback mechanism for the file changes (usually copy-rename stuff). 您仍然需要为文件更改实现回滚机制(通常是复制重命名的内容)。

There are a couple of other solutions or workarounds, depending on your specific system. 根据您的特定系统,还有其他几种解决方案或解决方法。 This questions is probably "too broad". 这个问题可能太广泛了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM