hibernate.order_updates:

Hibernate文档中提到,该配置用于在刷新一级缓存,提交UPDATE的时候,按照每类对象的主键顺序排序后再提交,可以在高并发情况下减少事务死锁的可能。这个配置默认为false,但是非常建议在可能存在高并发情况下开启,因为其实按照类型ID排序(在内存中),并不会消耗过多性能。那么这个配置到底什么含义呢?做个简单的测试。

首先准备一个对象User,完成映射(略),完成下面的测试:

  @Before
   public void save(){
   Session session=sf.openSession();
   session.beginTransaction();
   for(int i=0;i<10;i++){
   User u=new User();
   u.setName(Math.random()+"");
   session.save(u);
   }
   session.getTransaction().commit();
   session.close();
   }

首先任意的保存10个对象,然后模拟高并发修改:

  @Test
   public void testUpdate() throws Exception{
   for(int i=0;i<10;i++){
   Thread t=new Thread(new Runnable() {
   Random random=new Random();
   public void run() {
   Session session=sf.openSession();
   session.beginTransaction();
   for(int i=0;i<5;i++){
   Long id= new Long(random.nextInt(10)+1);
   System.out.println(Thread.currentThread().getName()+" "+id);
   User u=(User)session.get(User.class,id);
   u.setName(Math.random()+"");
   }
   session.getTransaction().commit();
   session.close();
   }
   },"thread"+i);
   t.start();
   }
   Thread.sleep(10000);
   }

该测试开启10个线程,在每个线程中的同一个事务中,随机得到5个User对象,并修改名字,然后提交事务。运行测试,99%的情况下都会报错:

  Caused by: com.mysql.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2941)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1623)
   at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1715)
   at com.mysql.jdbc.Connection.execSQL(Connection.java:3249)
   at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1541)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1455)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1440)
   at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133)
... 16 more

造成了死锁,异常产生原因简单分析如下:

假设Thread1得到的User对象的顺序为1,4,6,9,3;Thread2得到的User对象的顺序为2,3,9,8,4;那么假设当Thread1运行到update4的时候,锁住ID:4这行数据,Thread2运行到update9,锁住ID:9这行数据,Thread1运行到update 9的时候等待Thread2释放ID:9这行数据的锁,Thread2运行到update 4的时候,等待Thread1释放ID:4这行数据的锁,造成死锁。

如果修改hibernate配置文件:

  <property name="hibernate.order_updates">true</property>

再次运行,运行测试成功。

在update的时候,ID排序了。执行过程简单分析如下:

Thread1得到User对象的顺序为1,4,6,9,3;但是在更新的时候顺序调整为1,3,4,6,9;

Thread2得到User对象的顺序为2,3,9,8,4;但是在更新的时候顺序调整为2,3,4,9,8;

那么当Thread2更新ID:3的时候,就会等着Thread1释放锁,而不会锁住任何ID:3之前的数据,所以不会造成Thread1的死锁,所以能正常运行。(MySQL总是一条一条执行SQL)。

个人认为这个选项建议设置为true。

Hibernate 配置详解(7)的更多相关文章

  1. Hibernate 配置详解(9)

    hibernate.cache.use_structured_entries Hibernate文档上介绍,该属性是用于把对象以一种更易读的方式放到二级缓存中,这样,在对二级缓存进行监控的时候就更容易 ...

  2. Hibernate 配置详解(2)

    6) hibernate.session_factory_name: 配置一个JNDI名称,通过Configuration对象创建的SessionFactory会绑定到JNDI下该名称中.一般名字格式 ...

  3. Hibernate 配置详解(5)

    9) hibernate.batch_fetch_style: 该配置是hibernate4.2.0新添加的,使用这个设置可以配置hibernate在做batch-fetch的时候,生成SQL的策略. ...

  4. Hibernate 配置详解(8)

    hibernate.generate_statistics 这个配置大家应该都很熟悉,用于开启Hibernate统计信息,便于对Hibernate相关性能调试提供数据依据.在开发过程当中,可以把这个选 ...

  5. Hibernate 配置详解(12) 补充

    hibernate.hbm2ddl.import_files_sql_extractor 这个配置项用于补充这篇文章: http://blog.csdn.net/stefwu/article/deta ...

  6. Hibernate 配置详解(12) 其实我也不想用这么土的名字

    hibernate.hbm2ddl.import_files 这个配置用于在hibernate根据映射文件执行DDL之前,如果我们自己设置了要事先运行的SQL文件,hibernate就会先执行这些SQ ...

  7. Hibernate 配置详解(11)

    hibernate.session_factory_name_is_jndi 配置hibernate.cfg.xml中SessionFactory的name属性是否作为JNDI名称绑定.默认是true ...

  8. hibernate二级缓存ehcache hibernate配置详解

    <!-----------------hibernate二级缓存ehcache------------------------->hibernate配置 <prop key=&quo ...

  9. Hibernate配置详解

    <!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式--> <?xml version='1.0' ...

随机推荐

  1. VC 为静态控件添加事件

    操作系统:Windows 7软件环境:Visual C++ 2008 SP1本次目的:为静态控件添加事件,如:STATIC.Picture Control等等 有时候我们找到一个图片,为对话框背景添加 ...

  2. Objective-C中的SEL、IMP和Class类型

    1.SEL类型 例子: SEL say;        SEL skin; Objective-C 在编译的时候, 会根据方法的名字(包括参数序列),生成一个用 来区分这个方法的唯一的一个 ID,这个 ...

  3. Swift - 正则表达式的使用(附用户名、邮箱、URL等常用格式验证)

    Swift虽然是一个新出的语言,但却不提供专门的处理正则的语法和类.所以我们只能使用古老的NSRegularExpression类进行正则匹配. 即先接受一个正则表达式的字符串,由此生成NSRegul ...

  4. 【视频】零基础学Android开发:蓝牙聊天室APP(四)

    零基础学Android开发:蓝牙聊天室APP第四讲 4.1 ListView控件的使用 4.2 BaseAdapter具体解释 4.3 ListView分布与滚动事件 4.4 ListView事件监听 ...

  5. ASP.NET - (Session)后台登陆时,判断是不是已经登陆,如果不是,跳转回登陆页

    admin(小写):用户输入的账户. password(小写):用户输入的密码. 1.先将用户名和密码,存储到Session会话中. Session["Admin"] = admi ...

  6. io 测试

    //其中能够实现编码的只有OutputStreamWriter和对应inputStreamReader package net; import java.io.BufferedWriter; impo ...

  7. 14.8.3 Identifying the File Format in Use 确认使用的文件格式;

    14.8.3 Identifying the File Format in Use 确认使用的文件格式: 如果 你启用一个不同的文件格式使用 innodb_file_format configurat ...

  8. swift_将UIDatePicker到达的传播之间的时间差在数小时出现页面的事

    今天,写swift demo当它来到了一个非常精彩的问题,我再次 present 使用页面出来 UIDatePicker 选择时间,然后再回到原来的主界面的时间,结果出现的问题:B页面的正常时间,传回 ...

  9. script:查看redo产生的历史信息

    script:查看redo产生的历史信息 SQL> alter session set nls_date_format='dd-mon-yy'; SQL>  set lines 160 p ...

  10. Hibernate(五)——经典解析一对一关联映射

    前面两篇介绍了多对一.一对多的映射.今天分享下一对一的关联映射关系.有两种策略可以实现一对一的关联映射:主键关联.唯一外键关联. 主键关联——两个表有完全相同的主键值,来表示它们的一对一的关系.数据库 ...