Hibernate/MySQL并发问题

2024-01-13

我得到一个极其奇怪的结果使用 Hibernate (4.1.9.Final) 和 MySQL (14.14 Distrib 5.5.29,InnoDB 表):

当我使用一个线程将某些内容持久保存到数据库并尝试使用另一个线程获取它时,Hibernate 并不总是能找到该实体。 (尽管事实上我在打开加载会话之前正确提交了事务并关闭了持久会话。)

一些观察结果:

  • I can not使用单线程程序重现这一点。

  • I can查看数据库中“丢失”的实体,并且

  • 如果我重新启动应用程序 Hibernatecan成功加载实体。

这是说明问题的 SSCCE。 (为简洁起见,省略了导入):

public class StressTest {

    static SessionFactory sessionFactory;

    public static void main(String[] args) throws InterruptedException,
                                                     ExecutionException {

        // Configure Hibernate
        Configuration conf = new Configuration();
        conf.setProperty("hibernate.dialect",
                         "org.hibernate.dialect.MySQLInnoDBDialect");
        conf.configure();

        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(conf.getProperties())
                .buildServiceRegistry();        

        sessionFactory = conf.buildSessionFactory(serviceRegistry);

        // Set up producer / consumer
        BlockingQueue<Long> queue = new LinkedBlockingQueue<Long>();

        new Consumer(queue).start();
        new Producer(queue).start();
    }

}

class DummyEntity {
    long id;
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }
}

生产者类(创建DummyEntities并坚持下去)。

class Producer extends Thread {

    BlockingQueue<Long> sink;

    public Producer(BlockingQueue<Long> sink) {
        this.sink = sink;
    }

    @Override
    public void run() {
        try {
            while (true) {

                Session session = StressTest.sessionFactory.openSession();

                DummyEntity entity = new DummyEntity();
                entity.setId(new Random().nextLong());

                session.beginTransaction();
                session.save(entity);
                session.getTransaction().commit();
                session.close();

                sink.put(entity.getId());
            }
        } catch (InterruptedException ignore) {
            System.exit(-1);
        }
    }
}

消费者类(负载DummyEntities来自数据库):

class Consumer extends Thread {

    BlockingQueue<Long> source;

    public Consumer(BlockingQueue<Long> source) {
        this.source = source;
    }

    @Override
    public void run() {

        try {
            while (true) {

                long entityId = source.take();

                Session session = StressTest.sessionFactory.openSession();
                Object entity = session.get(DummyEntity.class, entityId);
                session.close();

                if (entity == null) {
                    System.err.printf("Entity with id %d NOT FOUND", entityId);
                    System.exit(-1);
                }
            }
        } catch (InterruptedException ignore) {
            System.exit(-1);
        }
    }
}

最后,这是映射-xmlDummyEntity.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping
    default-cascade="all"
    default-lazy="false">

    <class name="se.stresstest.DummyEntity">

        <id name="id" type="long">
            <generator class="assigned"/>
        </id>

    </class>

</hibernate-mapping>

结果输出总是以类似以下内容结尾:

Entity with id -225971146115345 NOT FOUND

有什么想法吗?

(This is a refined version of a previous question https://stackoverflow.com/questions/15806893/threading-issues-with-hibernate.)


此行为可以与 REPEATABLE READ 的事务隔离模式一致,这恰好是 InnoDB 的默认事务隔离模式:

http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_repeatable-read http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_repeatable-read

如果您的应用程序逻辑依赖于能够查看其他事务中提交的数据after当前事务已启动 - 以可重复读取为代价(数据可能/将会因其他事务中的操作而更改) - 您应该将事务隔离设置为 READ COMMITTED:

http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_read-comfilled http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_read-committed

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate/MySQL并发问题 的相关文章

随机推荐

  • 基于不同XAML的样式继承

    如何将样式中的 BasedOn 标记指定为在其他文件中定义的样式 Example Dictionary1 xaml 定义 在 Dictionary2 xaml 中我需要类似的东西
  • 从 pandas 数据框中删除闰年日

    我有福尔 数据框 datetime 2012 01 01 125 5010 2012 01 02 125 5010 2012 01 03 125 5010 2012 02 04 125 5010 2012 02 05 125 5010 20
  • 我是否需要担心“Rc”的开销?

    我是否正确地假设唯一 放慢速度 的事情Rc问题是它会在对象删除时检查是否释放该对象 除此之外 取消引用的开销是 多少 Rc 即我应该关心它吗 这两个函数几乎同样快吗 或者说速度上有明显的区别吗 fn test with box let b
  • 日志记录和同步

    我刚刚编写了自己的日志框架 非常轻量级 不需要大型日志框架 它由一个接口 ILogger 和许多实现该接口的类组成 我有一个问题是 TGUILogger 它采用 TStrings 作为日志记录目标 并将日志记录与主线程同步 以便列表框的 I
  • Linux 中如何给线程命名? [复制]

    这个问题在这里已经有答案了 我有一个用 C C 编写的多线程 Linux 应用程序 我有为我的线程选择名称 https stackoverflow com questions 149932 naming conventions for th
  • Java正则表达式跳过匹配

    我有一些文字 我想提取不以标点符号分隔的单词对 这是代码 n grams Pattern p Pattern compile a z if n 2 p Pattern compile a z a z if n 3 p Pattern com
  • 如何在supervisor中添加延迟到受监督进程 - linux

    我添加了一个使用 python cassandra 库的 Bottle 服务器 但它存在以下错误 Bottle FATAL Exited too quickly process log may have details 日志显示 File
  • Android JNI 本机 C 函数调用杀死活动

    什么有效 我有一个运行 TUN TAP 服务的 c 可执行文件 以及两个在终端中运行良好的 shell 脚本 用于配置 ip 路由 和 iptables 全部以 root 身份运行 什么不起作用 我正在尝试创建一个 Android 应用程序
  • 如何在 Python 中提取字符串中的列表?

    我使用 Pandas 导入了 CSV 并用字符串条目读入了一列 检查本系列 专栏 的条目 我发现它们实际上应该是列表 例如 df A pd Series entry11 entry21 entry22 entry31 entry32 我想从
  • Windows批处理文件中的一个数字既大于又小于另一个

    我的批处理文件中有以下代码 if bakfilesize geq freespacet echo baksize is larger if bakfilesize leq freespacet echo baksize is smaller
  • 如何在服务生成器类中添加http拦截器

    我创建了一个单独的服务生成器类 如本指南所示https futurestud io tutorials retrofit 2 manage request headers in okhttp interceptor https future
  • 如何将 CSRF 令牌设置为不同的上下文路径

    我们基于 Angular 的 Web 应用程序与在不同域和上下文路径上运行的企业门户集成 我正在使用基于 Spring Security 的 CSRF 令牌来验证传入请求 该应用程序在本地完美运行 但当我将其与门户集成时 所有 post 调
  • pg_dump 串行数据类型问题

    有人可以向我解释一下为什么使用以下脚本创建 PostgreSQL 表 CREATE TABLE users id serial NOT NULL name character varying 150 NOT NULL surname cha
  • 开发 API - 如何确保其安全? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我将读取和写入方法放在数据库中 并通过 URL 公开它们 我使用 CodeIgniter 框架并使用 URL 段将参数传递给这些方法
  • 将文件复制到 FTP 并以今天的日期存档

    我需要创建一个执行以下操作的脚本 将文件夹中的所有文件复制到 FTP 站点 如果复制成功 则将文件移至存档 存档应该是一个新创建的文件夹 具有今天的日期 这样我们就知道它们何时被传输 我试图蚕食其他脚本来让某些东西发挥作用 但我没有取得任何
  • docker ubuntu /bin/sh: 1: locale-gen: 未找到

    我将下面的区域设置代码放入我的 dockerfile 中 FROM node 4 onbuild Set the locale RUN locale gen en US UTF 8 ENV LANG en US UTF 8 ENV LANG
  • 如何在返回 SELF 的函数的 pl/sql 对象类型中链接调用

    我想让一个 oracle 对象返回自身并能够链接这些调用 我怎么做 我尝试返回相同的类型 但它不起作用 我还尝试添加一个由函数调用的过程 但它也不起作用 总是抱怨修改宽度成员的值 看起来函数不会产生副作用 它们是按照更数学的函数原理建模的吗
  • 使用QUdpSocket发送数据报

    我正在尝试使用 QUdpSocket 发送数据报 以下是我正在使用的代码 udpSocket new QUdpSocket this QByteArray datagram Message udpSocket gt writeDatagra
  • 将数据拟合到所有可能的分布并返回最佳拟合[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个样本数据 我想获得最佳拟合分布 我有几个链接建议我可以从以下位置导入发行版scipy stats 但是我事先并不知道数据的类型 我
  • Hibernate/MySQL并发问题

    我得到一个极其奇怪的结果使用 Hibernate 4 1 9 Final 和 MySQL 14 14 Distrib 5 5 29 InnoDB 表 当我使用一个线程将某些内容持久保存到数据库并尝试使用另一个线程获取它时 Hibernate