如何保证SQL行之间的约束?

发布于 2024-12-01 12:59:35 字数 395 浏览 2 评论 0原文

我们正在开发在线时间表应用程序。一个时间表可以由多个用户同时编辑。有一个非常重要的业务限制。一天内只能发生三件事。

从技术上讲,简单地说,数据库中有一个表,其中包含以下列: |编号 |活动 |日期|。应用程序在事务“select...count...where...”中运行,如果结果小于 3,则插入新事件。

有什么方法可以保证两个线程一天不会创建四个事件?这是一个经典的检查和写入问题。我们想知道如何在数据库层面解决这个问题?

使用事务并不能保证在第二个事务中另一个线程不会执行相同操作:检查事件数是否小于 3 并进行插入。锁定整个表是不可接受的,因为它会减少响应时间、并发性等。

应用程序是使用 Spring、Hibernate、MySQL 用 Ja​​va 开发的。

预先感谢您的任何建议。

We are developing online schedule application. One schedule can be edited simultaneously by several users. There is one very important business constraint. There must be only three events in one day.

Technically speaking and simplifying, there is a table in database with columns: | id | event | date |. Application runs in transaction "select... count... where..." and if result is less than 3, it inserts new event.

Wich approaches can be used to guarantee that two threads will not create four events in one day? This is a classical check-and-write problem. And we wonder how it can be solved on database level?

Using transactions doesn`t guarantee that in the second transaction another thread will not do the same: checks that number of events is less than 3 and makes insert. Locking the whole table is not acceptable because it will reduce response time, concurrency, etc.

Application is developed in Java using Spring, Hibernate, MySQL.

Thanks in advance for any pieces of advice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猫腻 2024-12-08 12:59:35

对于阻塞进程,您应该使用 Select ... FOR UPDATE 语句。但这个只适用于innodb。

示例:

//java logic
try {
    //mysql logic
    start transaction;
    select * from where 'some condition' FOR UPDATE
    INSERT INTO TABLE ....    
    commit;
//java logic
catch (Exception e) {
    rollback;
}

查看有关特定行锁定的更多信息 http:// dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

For blocking process you should use Select ... FOR UPDATE statement. But this one works only in innodb.

Example:

//java logic
try {
    //mysql logic
    start transaction;
    select * from where 'some condition' FOR UPDATE
    INSERT INTO TABLE ....    
    commit;
//java logic
catch (Exception e) {
    rollback;
}

See more info about specific row locking http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

游魂 2024-12-08 12:59:35

对于您的数据模型,您可以使用检查约束来计算行数。 AFAIK MySQL 本身并不支持这种类型的约束,但看起来可以用或者

,您可以考虑使用带有 days 表和 events 表的不同数据模型。您可以使用乐观锁定 ,以确保第二笔交易不会对数据有过时的理解。

With your data model you could use a check constraint to count the number of rows. AFAIK MySQL doesn't natively support this type of constraint, but it looks like it's possible to emulate them with a trigger

Alternatively you could consider a different data model with a days table and an events table. You could use optimistic locking of days to ensure that a second transaction didn't have an out of date understanding of the data.

北城孤痞 2024-12-08 12:59:35

由于您正在使用 Spring,并且存在并发问题,因此请尝试在 Java 层而不是 DB 层同步执行。当我们尝试使用数据库来维护并发时,我们也遇到过类似的问题。

也许您可以在 Java 中使执行块同步,以便强制执行阻塞;在同步方法内,检查所有业务逻辑是否返回 true。如果为 true,则继续正常执行。如果为 false,则异常中止。

Since you are going through Spring, and since there is a concurrency issue, try synchronizing execution at the Java layer, rather than at the DB layer. We've had similar issues when trying to use a DB to maintain concurrency.

Perhaps you could make the execution block in Java synchronized so that it forces execution to block; inside the synchronized method, check that all of your business logic returns true. if true, continue with normal execution. If false, abort with an exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文