简体   繁体   English

Web应用程序中的并发控制

[英]Concurrency control in web application

I have to solve this situation: in my Spring + JPA web application I have a jsp similar to an excel work sheet. 我必须解决这种情况:在我的Spring + JPA Web应用程序中,我有一个类似于excel工作表的jsp。

So I have a certain number of cells and each cell is saved in a DB table with additional information: I have a row for each cell. 所以我有一定数量的单元格,每个单元格都保存在DB表中,并附加了相关信息:每个单元格都有一行。

id | value | column | row | ...

I use this structure because number of columns in my jsp table is dynamic. 我使用这种结构,因为我的jsp表中的列数是动态的。

At the moment, when I save cells I truncate the current set of rows in DB table and re-insert all the new rows . 目前,当我保存单元格时, 我会截断DB表中的当前行集并重新插入所有新行 This is the fastest way I found to update a large set of rows. 这是我发现更新大量行的最快方法。

But now I have a concurrency problem: the jsp page can be used by different users at the same time and this can cause overwriting problems on other users savings . 但是现在我遇到了并发问题: jsp页面可以被不同的用户同时使用,这可能会导致其他用户节省的覆盖问题

I need to implement some kind of lock in my web app. 我需要在我的网络应用程序中实现某种锁定。 I found there are mainly two types of lock: optimistic vs pessimistic. 我发现主要有两种锁:乐观与悲观。

Can you suggest me a common approach to solve this situation? 你能建议我解决这种情况的常用方法吗? Where do I need to implement the lock, at data access level or at service level? 在数据访问级别或服务级别,我需要在哪里实现锁定?

NOTE to be more clear: table values are shared among users, but can be updated by anyone among authorized users. 请注意更清楚:表值在用户之间共享,但可由授权用户中的任何人更新。

The solution would probably depend on the behavior requirements. 解决方案可能取决于行为要求。

How about the following scenario: users A and B started to change some values, then user A pressed Save button and saved data, after that user B did the same. 以下场景如何:用户A和B开始更改某些值,然后用户A按下保存按钮并保存数据,之后用户B执行相同操作。 User B got an error message saying something like "the data has been updated, please reload the page". 用户B收到错误消息,提示“数据已更新,请重新加载页面”。 He reloads the page and lose all changes he did :( Only after that he is able to save his changes, but he has to do it once again. 他重新加载页面并失去他所做的所有更改:(只有在那之后他才能保存他的更改,但他必须再次这样做。

Other possible scenario: users A and B accessing the page, but only the user who was the first will be able to save his work, other users will see message saying something like "someone else is editing the page, try again later". 其他可能的情况:用户A和B访问该页面,但只有第一个用户能够保存他的工作,其他用户将看到消息说“别人正在编辑该页面,稍后再试”。

For the first scenario you can implement the following: each line of the table (in database) has a last-update-timestamp which is updated to current time each time this row is changed. 对于第一个场景,您可以实现以下内容:表的每一行(在数据库中)都有一个last-update-timestamp,每次更改此行时都会更新为当前时间。 Now, let's imagine user A get row with timestamp 1 when opened the page, user B was a little bit slower and got the same row with timestamp 2 . 现在,让我们假设用户A在打开页面时获得时间戳为1行,用户B稍微慢了一点,并且时间戳为2 But, he did his changes faster and pressed Save button first. 但是,他更快地完成了他的更改,并先按下保存按钮。 Now, the row is saved in DB with timestamp let's say 5 . 现在,该行保存在DB中,时间戳记为5 User A is trying to save his changes, but the timestamp of his data is 1 , which is different from 5 currently in DB. 用户A正在尝试保存他的更改,但他的数据的时间戳为1 ,这与当前在DB中的5不同。 That means someone changed that data already and he should see error message I mentioned above. 这意味着有人已经更改了这些数据,他应该看到我上面提到的错误消息。

Second scenario is a little bit harder to implement. 第二种情况实施起来有点困难。 I think the best way to do this is to open transaction to DB which 我认为最好的方法是打开事务到DB

  • reads the row(s) we want; 读取我们想要的行;
  • put some flag like "locked" to true for all of them; 把一些标志,如“锁定”,以true为他们所有;
  • if some row is locked already, fails (or return available rows, depending on what you need). 如果某行已被锁定,则失败(或返回可用行,具体取决于您的需要)。 But, probably should fail; 但是,可能应该失败;
  • returns rows to jsp page; 将行返回到jsp页面;

Now, if other user requested the same rows, transaction will fail and he will not be able to start changing data. 现在,如果其他用户请求相同的行,则事务将失败,并且他将无法开始更改数据。

User A should put these locked flags back to false when he saves the data. 用户A在保存数据时应将这些locked标志置回false Important thing : these locks should have timeout to prevent situation when user opened the page and closed it without saving (or browser crash, or something else). 重要的是 :这些锁应该具有超时以防止用户打开页面并关闭它而不保存(或浏览器崩溃或其他)时的情况。 You may also want to implement some kind of lock reackquire for the same user - when user opened the page for the first time, then closed it without saving data and opened once again - he should be able to edit the data. 您可能还想为同一个用户实施某种锁重新加载 - 当用户第一次打开页面,然后关闭它而不保存数据并再次打开 - 他应该能够编辑数据。 This can be done by identifying user somehow - login, cookie, and so on. 这可以通过以某种方式识别用户来完成 - 登录,cookie等。

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

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