精华内容
下载资源
问答
  • 比如隔离级别设置为串行化,事务T1有两个查询均是select * from person有8条记录,在第一次查询、第二次查询前,另一个线程开启一个新事务T2,做了一笔插入操作并提交,此时数据库中真实数据有9条。然后我们的事务...

    注:这里只观察表象和库中真实数据,没有深究不同的事务间隔离级别是怎样影响锁机制的,也没有深究oracle是怎么使用在undo表空间中构造并使用旧的数据块的。

    注:Oracle通过在undo表空间中构造多版本数据块来实现读一致性,支持serializable的隔离级别,可以实现最高级别的读一致性。每个session 查询时,如果对应的数据块发生变化,Oracle会在undo表空间中为这个session构造它查询时的旧的数据块。oracle数据库通过这种能力,来保证在serializable级别的时候,不是锁表不让其他事务插入或删除,而是其他事务能操作,本事务中的多次查询还是使用旧数据块,以此达到事务间多次查询的记录的一致性。

    注:oracle数据库只支持读已提交Read Commited 和串行化Serializable这两个隔离级别,且oracle默认的隔离级别就是Read Commited。

    测试准备:数据库配置文件、得到connction的工具类、写一个java类、已经存在3条数据的表person、使用plsql Dev工具。

    Druid.properties

    #driverClassName=com.mysql.jdbc.Driver
    #url=jdbc:mysql:///day15
    driverClassName=oracle.jdbc.driver.OracleDriver
    url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
    username=XXX
    password=XXX
    initialSize=5
    maxActive=10
    maxWait=3000

    JDBCUtils.java

    package com.amar.utils;
    
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    import javax.sql.DataSource;
    
    
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    /**
     * Druid连接池的工具类
     */
    public class JDBCUtils {
    
        //1.定义成员变量 DataSource
        private static DataSource ds ;
    
        static{
            try {
                //1.加载配置文件
                Properties pro = new Properties();
                pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
                //2.获取DataSource
                ds = DruidDataSourceFactory.createDataSource(pro);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取连接
         */
        public static Connection getConnection() throws SQLException {
    //        return ds.getConnection();
        	Connection conn = ds.getConnection();
        	conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//读已提交的事务间隔离级别,也是默认的。注:不能是sys用户
    //    	conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);//读未提交的事务间隔离级别。注:oracle不支持此隔离级别,会报nullPointEx
        	return conn;
        }
    
        /**
         * 释放资源
         */
        public static void close(ResultSet rs , Statement stmt, Connection conn){
    
            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
    
            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if(conn != null){
                try {
                    conn.close();//归还连接
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 获取连接池方法
         */
    
        public static DataSource getDataSource(){
            return  ds;
        }
    
    }
    
    

    testTxInsulate.java

    package com.amar.oracleTx;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    
    import com.amar.utils.JDBCUtils;
    
    public class testTxInsulate {
    public static void main(String[] args) {
    	System.out.println("mian线程的名字:==="+Thread.currentThread().getName());
    //	再造一个线程
    	Thread myThread1=new Thread(new Runnable() {
    		Connection conn;
    		PreparedStatement pre;
    		ResultSet result;
    		
    		@Override
    		public void run() {
    			System.out.println("自己定义一个线程的名字是:==="+Thread.currentThread().getName());
    			try {
    				 conn = JDBCUtils.getConnection();
    				 conn.setAutoCommit(false);//设置手动管理事务
    				 String sql = "select * from person ";
    			        pre = conn.prepareStatement(sql);
    			        result = pre.executeQuery();
    			        while (result.next()){
    			            System.out.println("线程1---人编号:" + result.getInt("id") + "   "+
    			            		"姓名:"+ result.getString("name")+"   "+
    			            		"年龄:"+ result.getString("age")
    			            		);}
    			        System.out.println("美丽的分割线------------------------");
    			        System.out.println("美丽的分割线------------------------");
    			        System.out.println("美丽的分割线------------------------");
    			        Thread.sleep(15000);
    			        //休眠15秒后第二次查询。
    			        sql = "select * from person ";
    			        pre = conn.prepareStatement(sql);
    			        result = pre.executeQuery();
    			        while (result.next()){
    			            System.out.println("线程1---人编号:" + result.getInt("id") + "   "+
    			            		"姓名:"+ result.getString("name")+"   "+
    			            		"年龄:"+ result.getString("age")
    			            		);}
    			      conn.commit();  
    			} catch (Exception e) {
    				try {
    					conn.rollback();
    				} catch (SQLException e1) {
    					e1.printStackTrace();
    				}
    				e.printStackTrace();
    			}finally {
    				JDBCUtils.close(result, pre, conn);
    			}
    		}
    	});
    	
    	myThread1.start();
    	
    	
    	
    	
    }
    }
    

           ID    NAME    AGE    BIRTHDAY
    1    1    哈1    25    2020/10/20 14:00:08
    2    2    哈2    25    2020/10/20 14:00:12
    3    3    哈3    25    2020/10/20 14:00:15
     

     

    上述代码已知,我们的级别是Read Commited;我们的java类里面有两次查询,由同一个事务控制,两次查询中间间隔15秒。下面我们测试它能不能解决读未提交的问题。

    启动main方法,在第一次查询后15秒内操作plsql工具执行update person p set p.name='哈3,大傻子' where p.id='3';且不提交,用来模拟并发的事务,分析两次查询对应的输出

    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3   年龄:25
    美丽的分割线------------------------
    美丽的分割线------------------------
    美丽的分割线------------------------
    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3   年龄:25

     所以:

    隔离级别是读已提交时,一次事务内的两次查询结果一样,不会被两次查询间隔时间内的并发事务的未提交的修改操作影响,即避免脏读(读未提交)。下面测试提交情况

    启动main方法,在第一次查询后15秒内操作plsql工具执行update person p set p.name='哈3,大傻子' where p.id='3';并提交,用来模拟并发的事务,分析两次查询对应的输出

    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3   年龄:25
    美丽的分割线------------------------
    美丽的分割线------------------------
    美丽的分割线------------------------
    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3,傻   年龄:25

    所以:

    隔离级别是读已提交时,一次事务内的两次查询结果不一样,会被两次查询间隔时间内的并发事务的提交的修改操作影响,即解决不了不可重复读问题。(不可重复读,即原始读取不可重复)。下面测试事务间隔离级别是串行化Serializable的时候( conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);)(数据要回到原始状态再测试)还执行上面的修改并提交操作。输出如下:

    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3   年龄:25
    美丽的分割线------------------------
    美丽的分割线------------------------
    美丽的分割线------------------------
    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3   年龄:25

    所以,串行化解决了不可重复读问题。那么此时我数据库中真实数据是什么呢?当然是被修改后的啦,毕竟你的修改操作都能提交呀。

    下面测插入操作并提交:insert into person values('4','哈4','24',sysdate);  commit;用来测试串行化能不能解决幻读的问题。(幻读:即第二次读取到的数据相比较第第次少了几条或者多了几条就好像产生了幻觉一样。就是说咦,我没新插入或删除记录啊,这次眼睛看到的多了或少了几条记录一定是幻觉。 )

    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3,傻   年龄:25
    美丽的分割线------------------------
    美丽的分割线------------------------
    美丽的分割线------------------------
    线程1---人编号:1   姓名:哈1   年龄:25
    线程1---人编号:2   姓名:哈2   年龄:25
    线程1---人编号:3   姓名:哈3,傻   年龄:25

    那么此时我数据库中真实数据有几条?当然是4条啦,毕竟你的插入操作都能提交的呀。

    总结:

    oracle在读已提交的事务间隔离级别下,能解决脏读问题,不能解决不可重复读的问题,本身就符合一般业务要求。

    oracle在串行化的事务间隔离级别下,并不会限制并发事务去修改或插入记录,而是以旧数据块的功能,来解决不可重复读或幻读的现象。

    (拓展:mysql在不同隔离级别下使用的锁机制就不同,比如串行化就会加表级共享锁,直到此事务结束才释放,这样其他事务就不能修改或增删记录了(因为要CRUD之前都要先能够持有某种锁),既然这样也就解决了脏读、不可重复读、幻读等问题。

    所以:oracle数据库隔离级别不仅要考虑不同级别对锁机制的影响,还要考虑oracle具有的旧数据块的影响。mysql数据库隔离级别只考虑不同级别对锁机制的影响即可

     

    为什么银行使用 oracle、大厂使用mysql                  :    https://new.qq.com/omn/20201004/20201004A0AKMR00.html

    深入分析mysql事务的隔离级别与锁机制之间关系    :   https://www.hollischuang.com/archives/943

     

     

    展开全文
  • java 1.7控制代码超时时间

    千次阅读 2017-04-26 10:42:50
    防止重复提交有多种方法,有一种方法是操作数据之前先向一个临时表(有主键约束)中插入一条数据,这条数据可以是单据的主键id。当后续用户重复提交时,由于主键冲突就会报错,然后系统提示重复提交。但现在出现了一...

        防止重复提交有多种方法,有一种方法是操作数据之前先向一个临时表(有主键约束)中插入一条数据,这条数据可以是单据的主键id。当后续用户重复提交时,由于主键冲突就会报错,然后系统提示重复提交。但现在出现了一个问题,如果首次提交的事务迟迟不不能提交(或许是功能慢),后面重复提交的事务就会产生锁。如何避免后面的锁呢?就需要在代码里面写上控制超时的时间:

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.TimeoutException;
    
    public class ThreadTimeoutTest {
        public static void main(String[] args) throws InterruptedException,
                ExecutionException {
            ExecutorService threadPool = Executors.newFixedThreadPool(1);
            Callable<String> call = new Callable<String>() {
                public String call() throws Exception {
                    //开始执行耗时操作
                    Thread.sleep(1000 * 5);
                    return "线程执行完成.";
                }
            };
            try {
                Future<String> future = threadPool.submit(call);
                String result = future.get(2000 * 1, TimeUnit.MILLISECONDS); //任务处理超时时间设为 2 秒
                System.out.println("任务成功返回:" + result);
            } catch (TimeoutException ex) {
                System.out.println("处理超时啦....");
                ex.printStackTrace();
            } catch (Exception e) {
                System.out.println("处理失败.");
                e.printStackTrace();
            }
            // 关闭线程池
            threadPool.shutdown();
        }
    }
    展开全文
  • spring中设置在java代码中的插入SQL表中看不到数据,而应用程序确可以查看到新数据,具体原因就是会话事务没有提交造 成,查阅了了一些资料解决方法如下:

    spring中设置<property name="defaultAutoCommit" value="false" />在java代码中的插入SQL后表中看不到数据,而应用程序确可以查看到新数据,具体原因就是会话事务没有提交造 成,查阅了了一些资料后解决方法如下:

    <!-- Connection Info -->
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="maxActive" value="${jdbc.pool.maxActive}" />
    <property name="maxIdle" value="${jdbc.pool.maxIdle}" />
    <property name="minIdle" value="0" />
    <property name="defaultAutoCommit" value="false" />
    <!-- 连接Idle10分钟后超时,每1分钟检查一次 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <property name="minEvictableIdleTimeMillis" value="600000" />
    <!--默认值是false,当连接池中的空闲连接是否有效 -->
    <property name="testWhileIdle" value="true"/>
    <!-- 默认值是true,当从连接池取连接时,验证这个连接是否有效-->
    <property name="testOnBorrow" value="true"/>
    <!--检查连接死活的时间间隔(单位:毫妙) 0以下的话不检查。默认是0。 -->
    <property name="validationInterval" value="30000"/>
    <!--默认值是flase,当把该连接放回到连接池的时,验证这个连接是 -->
    <property name="testOnReturn" value="true"/>  
    <!--一条sql语句,用来验证数据库连接是否正常。这条语句必须是一个查询模式,并至少返回一条数据。可以为任何可以验证数据库连接是否正常的sql-->
                <property name="validationQuery" value="select 1"/>  
                
                <property name="commitOnReturn" value="true"/>

    展开全文
  • 是因为我调用了个`dao`层的插入数据的方法吗?** 还是或事物回滚就是从头在执行要一遍流程呢? 这个异常, 导致回滚技术无法实现呀. ## 代码片段(图片) ![图片说明]...
  • mysql插入性能测试

    2020-02-16 14:25:58
    使用java直接连接数据库,用多线程测试,每个线程一个数据库连接,事务自动提交。每个线程完成批量插入后才关闭连接。 mysql没有进行线程优化,都是使用默认配置。 三、测试数据 1、1核,单表,innoDB ...

    一、环境

    vm虚拟机,centos7,MySQL5.7,jdk8

    两台机器是局域网

    二、测试代码

    数据表:16个分表,表结构是20个字段,15个字段的长度是100个字符填充。

    使用java直接连接数据库,用多线程测试,每个线程一个数据库连接,事务自动提交。每个线程完成批量插入后才关闭连接。

    mysql没有进行线程优化,都是使用默认配置。

    三、测试数据

    1、1核,单表,innoDB

    每个线程插入条数 单线程耗时 线程数 总tps
    10万 63s 1个 1500条
    10万 78s 2个 2564条
    10万 127s 4个 3149条
    10万 224s 8个 3571条
    10万 340s 12个 3529条

     

     

     

     

     

    2、4核,单表,innoDB

    每个线程插入条数 单线程耗时 线程数 总tps
    10万 60s 1个 1666条
    10万 64s 2个 3200条
    10万 97s 4个 4123条
    10万 195s 8个 4100条
    10万 325s 12个 3600条

     

     

     

     

     

    3、1核,16个表,MyISAM

    每个线程插入条数 单线程耗时 线程数 总tps
    2万 10s 1个 2000条
    5000 2s 2个 5000条
    5千 2s 4个 10000条
    5千 5s 8个 8000条
    5千 10s 16个 8000条

     

     

     

     

     

    4、2核,16个表,MyISAM

    每个线程插入条数 单线程耗时 线程数 总tps
    2万 7s 1个 3000条
    5000 2s 2个 5000条
    5千 2s 4个 10000条
    5千 5s 8个 8000条
    5千 12s 16个 6666条

     

     

     

     

     

    5、4核,16个表,MyISAM

    每个线程插入条数 单线程耗时 线程数 总tps
    2万 11s 1个 1176条
    5000 3s 2个 3300条
    5千 5s 4个 4000条
    5千 11s 8个 3636条
    5千 15s 16个 5333条

     

     

     

     

     

    四、测试结论

    1、在某些条件下MyISAM的插入效率比innoDB快。

    2、连接数是服务器核数的两倍时,可获得最佳的插入性能。

    3、多连接数时,InnoDB实例的tps是:2500-4100,MyISAM实例的tps是:3300-1万

    4、Sysbench基准测试,10个线程,10个表,每个表插入10万条数据,结果如下:

    五、理论

    1、当服务器核数,数据库连接数,数据库内部线程数一样的情况下,多核应该是单核的倍数,但是测试时没有证明这点,可能是mysql线程配置不是最优的。

    2、MyISAM时,4核的tps居然比2核的低很多,这个很难解释。

    展开全文
  • java面试题

    2018-04-27 19:55:38
    5:提交事务 6:关闭Session 7:关闭SessionFactory Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。 Spring由那几个模块组成? 答:Spring主要由7个模块组成...
  • java面试800题

    2011-09-13 20:25:48
    事务开始执行,它对系统中数据的改变应该是恒定的,不应受其它操作或故障的影响。 " Q0062 事务有几种属性?分别是什么? "事务的属性有6种 1.Required:当处于事务范围内的客户端应用调用组件商务方法时,组件...
  • Javashop开发规范V2.2

    2012-08-21 00:13:09
    3.2.6 插入数据 <command>insert <table>es_adcolumn <fields>acid,cname,width,height,atype,disabled <values>5,'列表页上部横幅','972px','67px',0,'false' 3.2.7 删除数据 暂未支持 3.2.8 更新数据 暂未...
  • Java开发实战1200例.第2卷.part3

    热门讨论 2013-05-08 22:46:34
    实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM函数实现数据汇总 161 实例088 利用AVG函数...
  • Java开发实战1200例.第2卷.part2

    热门讨论 2013-05-08 22:45:35
    实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM函数实现数据汇总 161 实例088 利用AVG函数...
  • Java开发实战1200例.第2卷.part1

    热门讨论 2013-05-08 22:44:13
    实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM函数实现数据汇总 161 实例088 利用AVG函数...
  •  1.7.7 提交(Commit)修改  1.7.8 添加文件和目录  1.7.9 删除文件和目录  1.7.10 查看文件的版本变革  1.7.11 提取文件以前版本的内容  1.7.12 从以前版本重新开始  1.7.13 创建标签  1.7.14 创建分支  ...
  • 25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
  • 14.5.1 Commit(提交) 391 14.5.2 Savepoint(保存点) 391 14.5.3 Rollback(回滚) 391 14.5.4 Set Transaction(设置事务) 391 14.5.5 Set Constraints(设置约束) 392 14.6 将运算分组为事务 392 14.7 订单录入...
  • 实例156 向数据表中插入数据的方法 实例157 数据修改的方法 实例158 数据删除的方法 实例159 数据分页的方法 实例160 对结果集进行分页的方法 实例161 关闭数据库的方法 实例162 数据库事务处理的方法 实例...
  • 实例084 使用UNION ALL语句批量插入数据 实例085 更新指定记录 实例086 将数据表清空 第4章 SQL语句应用技术 4.1 聚集函数与日期查询 实例087 利用SUM函数实现数据汇总 实例088 利用AVG函数实现计算平均值 实例089 ...
  • 实例084 使用UNION ALL语句批量插入数据 实例085 更新指定记录 实例086 将数据表清空 第4章 SQL语句应用技术 4.1 聚集函数与日期查询 实例087 利用SUM函数实现数据汇总 实例088 利用AVG函数实现计算平均值 实例089 ...
  • 实例084 使用UNION ALL语句批量插入数据 实例085 更新指定记录 实例086 将数据表清空 第4章 SQL语句应用技术 4.1 聚集函数与日期查询 实例087 利用SUM函数实现数据汇总 实例088 利用AVG函数实现计算平均值 实例089 ...
  • 实例156 向数据表中插入数据的方法 实例157 数据修改的方法 实例158 数据删除的方法 实例159 数据分页的方法 实例160 对结果集进行分页的方法 实例161 关闭数据库的方法 实例162 数据库事务处理的方法 实例...
  • 《阿里巴巴 Java开发手册》读感 JVM如何从入门到放弃的? 记一次愚蠢的操作--String不可变性 记一次愚蠢的操作--线程安全问题 小白入门学习打日志 最近学到的Lambda表达式基础知识 手把手带你体验Stream流 几个...
  • sqlite3数据库的性能问题报告

    千次阅读 2005-07-02 19:00:00
    使用jdbc测了一下sqlite3的插入数据的效率,使用整体事务与不使用整体事务,差别非常明显。 cpu: 1G, 内存:512MB使用整体事务:1000000条记录,需要93秒钟。使用逐个插入提交事务:1秒钟只能处理20条记录。启动程序...
  • (按道理,两个SQL语句应该是两个事务,应该能使用刚刚插入数据,这是第一个疑问,是不是客户端造成的,我的客户端设置是自动提交SQL,不应该有问题) 方案2:在第一种方案不能满足需求,我寻求了第二种方案,...
  • @AfterThrowing: 用来处理当织入的代码抛出异常的逻辑处理; @Around: 环绕,可以在切入点前后织入代码,并且可以自由的控制何时执行切点; 应用:使用自定义注解 和 AOP 切面统一打印出入参日志 1.2 自定义 ...
  • 实战系列02:包学会,教你用Java函数式编程重构烂代码 实战系列03:请避开Stream流式编程常见的坑 实战系列04:使用Java8 Optional类优雅解决空指针问题 数据结构和算法 学什么? 有些同学可能要问了:我学 Java ...
  •  在程序中优化查询而无需改动代码。  作为Oracle SQL经典著作之一,本书为SQL开发人员指明了前行的方向,赋予了他们不断开拓的动力。 作者简介  KAREN MORTON 研究人员、教育家及顾问,Fidelity信息服务公司...

空空如也

空空如也

1 2 3 4
收藏数 66
精华内容 26
关键字:

java插入数据后提交事务代码

java 订阅