JDBC学习笔记——事务、存储过程以及批量处理

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1、事务                                                                                   

1.1、事务的基本概念和使用示例

      数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。

      JDBC可以操作Connection的setAutoCommit()方法,给它false参数,提示数据库启动事务,在下达一连串的SQL命令后,自行调用Connection的commit()方法,提示数据库确认(Commit)操作。如果中间发生错误,则调用rollback(),提示数据库撤销(ROLLBACK)所有执行。同时,如果仅想要撤回某个SQL执行点,则可以设置存储点(SAVEPOINT)。一个示范的事务流程如下:

Connection conn = ...;
Savepoint point = null;
try {conn.setAutoCommit(false);Statement stmt = conn.createStatement();stmt.executeUpdate("INSERT INTO ...");...point = conn.setSavepoint();stmt.executeUpdate("INSERT INTO ...");...conn.commit();
} catch (SQLException e) {e.printStackTrace();if (conn != null) {try {if (point == null) {conn.rollback();} else {conn.rollback(point);conn.releaseSavepoint(point);}} catch (SQLException ex) {ex.printStackTrace();}}
} finally {...if (conn != null) {try {conn.setAutoCommit(true);conn.close();} catch (SQLException ex) {ex.printStackTrace();}}
}

      需要说明的是,JDBC操作事务的前提条件是数据库支持事务,如果数据库本身不支持事务,那么我们即使调用setAutoCommit(false)也无法启动事务。对于MYSQL来说,MyIsam数据库引擎不支持事务操作,InnoDB数据库引擎支持事务操作。  

1.2、隔离级别

      要理解隔离级别,首先要了解多个事务并行时,可能引发的数据不一致问题有哪些,常见的事务并行引发问题有以下几类:

更新遗失

      更新遗失是指某个事务对字段进行更新的信息,因另一个事务的介入而遗失更新的效力,一个简单的示例如下:

  1. 事务A更新数据表字段为AAA;
  2. 事务B更新数据表字段为BBB;
  3. 事务A提交;
  4. 事务B提交。

      这个序列就是典型的更新丢失,因为第三步所做的所有修改全部会丢失。如果要避免更新遗失问题,可以设置隔离级别为"read uncommitted",这样A事务已更新但未确认的数据,B事务仅可做读取操作,但不可做更新操作。这样上面的四个步骤就是不合法的,必须A事务完全提交,B事务才能做更新操作。

脏读

      "read uncommitted"隔离级别保证了在A事务提交之前,B事务不能做更改操作,但是没有阻止B事务做读取操作,但是这个其实是有问题的:如果A事务更新字段为"AAA",B事务读取值为"AAA"并使用,然后A事务回滚事务,那么B事务读取的"AAA"就属于脏数据。如果要避免脏读问题,可以设置隔离级别为"Read Commited",也就是事务读取的数据必须是其他事务已经确认的数据。

不可重复读

      不可重复度是指两次读取同一字段的数据不一致,例如:事务A读取字段为"AAA",事务B更新数据为"BBB",事务B提交,事务A读取字段为"BBB",事务A连续的两次读取,字段值不一样。要避免这种问题,可以设置数据库隔离级别为"Repeatable Read",对于这种隔离界别,事务A读取字段为"AAA"后,其他事务在事务A提交前只可读取该字段,不可更新该字段。

幻读

      幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的"全部数据行"。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入"一行新数据"。那么,以后就会发生操作第一个事务的用户发现表中还是有没有修改的数据行,就好象发生了幻觉一样。要解决幻读问题,必须设置隔离级别为Serializable,Serializable是数据库隔离级别的最高级别,串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读,但是执行效率慢,需要谨慎使用。

      可以使用以下命令查询mysql的隔离级别:

 

select @@global.tx_isolation,@@tx_isolation;

 

1.3、悲观锁、乐观锁

      悲观锁是采用一种悲观的态度来对待事务并发问题,认为系统中的并发更新会非常频繁,并且事务失败了以后重来的开销很大,这样一来,我们就需要采用真正意义上的锁来进行实现。悲观锁的实现,往往依靠数据库提供的锁机制。悲观锁的基本思想就是每次一个事务读取某一条记录后,就会把这条记录锁住,这样其它的事务要想更新,必须等以前的事务提交或者回滚解除锁。

       乐观锁,顾名思义就是保持一种乐观的态度,我们认为系统中的事务并发更新不会很频繁,即使冲突了也没事,大不了重新再来一次。它的基本思想就是每次提交一个事务更新时,我们先看看要修改的东西从上次读取以后有没有被其它事务修改过,如果修改过,那么更新就会失败。乐观锁的实现方式大多是基于数据版本 ( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

      总的来说,悲观锁的机制依赖数据库的锁机制,较安全,而乐观锁机制通过应用程序控制,性能较好。

1.4、分布式事务

 

      分布式事务处理涉及多个分布在不同地方的数据库,但对数据库的操作必须全部被提交或者回滚。只要任一数据库操作时失败,所有参与事务的数据库都需要回滚。
      Open 组织定义的分布式事务处理模型X/Open DTP 模型包括应用程序( AP )、事务管理器( TM )、资源管理器( RM ,即数据库 )、通信资源管理器( CRM )四部分。而 XA 是 X/Open DTP 定义的事务管理器与数据库之间的接口规范(即接口函数),事务管理器用它来通知数据库事务的开始、结束以及提交、回滚等。
      XA 接口规范使用两阶段提交协议来完成一个全局事务,保证同一事务中所有数据库同时成功或者回滚。
      两阶段提交协议假设每个数据库点都存在一个write-ahead log,每一次的write请求都是先记log后才真正执行写入。


第一阶段为提交请求阶段(Commit-request phase):
      1. 事务管理器给所有数据库发query to commit消息请求,然后开始等待回应;
      2. 数据库如果可以提交属于自己的事务分支,则将自己在该事务分支中所做的操作固定记录下来(在undo log和redo log中各记一项);
      3. 数据库都回应是否同意提交的应答。
第二阶段为提交阶段(Commit phase):
    如果事务管理器收到的所有回应都是agreement,
      1. 事务管理器记日志并给所有数据库发commit消息请求;
      2. 各个数据库执行操作,释放所有该事务相关的锁和资源;
      3. 各个数据库给事务管理器回复;
      4.当收到所有回复,事务管理器结束当前事务

 

    如果事务管理器收到的任一回应是abort,
      1. 事务管理器记日志并给所有数据库发rollback消息请求;
      2. 各个数据库执行undo操作,释放所有该事务相关的锁和资源;
      3. 各个数据库给事务管理器回复;
      4.当收到所有回复,事务管理器结束当前事务

 

      两阶段提交协议的问题在于数据库在提交请求阶段应答后对很多资源处于锁定状态,要等到事务管理器收集齐所有数据库的应答后,才能发commit或者rollback消息结束这种锁定。锁定时间的长度是由最慢的一个数据库制约,如果数据库一直没有应答,所有其他库也需要无休止的锁并等待。并且,如果事务管理器出现故障,被锁定的资源将长时间处于锁定状态。无论是任一数据库或者事务管理器故障,其他数据库都需要永久锁定或者至少长时间锁定。并且,分布式系统中节点越多,存在缓慢网络或者故障节点的概率也就越大,资源被长时间锁定的概率指数上升。
      两阶段提交协议的另一个问题是只要有任意一个数据库不可用都会导致事务失败,这导致事务更倾向于失败。对于多个副本的备份系统,很多时候我们希望部分副本点失效时系统仍然可用,使用该协议则不能实现。并且,分布式系统中节点越多,存在故障节点的概率也就越大,系统的可用性指数下降。
另外,如果数据库在第一阶段应答后到第二阶段正式提交前的某个阶段网络故障或者节点故障,该协议无法提交或回滚,数据不一致不能绝对避免。

 

2、存储过程                                                                              

      JDBC可以调用存储过程,要调用存储过程,首先我们应该创建存储过程:

//创建表,并插入数据
create table g(num int,value  varchar(10));  
insert into g values(1, '1'),(10, '10'),(60, '60'),(100, '100');//创建存储过程
DELIMITER $
CREATE PROCEDURE p1(IN n int, OUT avg double, OUT min int)
BEGINselect avg(num) from g where num > n INTO avg;select min(num) from g where num > n INTO min;
END$
DELIMITER ;

  JDBC调用存储过程的接口与增删改查的不同,JDBC调用存储过程应该使用CallableStatement,简单示例如下:

private static void ps() throws SQLException{Connection conn = null;CallableStatement cs = null;try{conn = JdbcUtils.getConnection();cs = conn.prepareCall("call p1(?,?,?)");cs.registerOutParameter(2, Types.DOUBLE);//设置out参数cs.registerOutParameter(3, Types.INTEGER);//设置out参数cs.setInt(1, 18);//设置in参数cs.executeUpdate();System.out.println(cs.getInt(2) + "   " + cs.getInt(3));} finally{JdbcUtils.free(null, cs, conn);}	
}  

3、批次更新                                                                             

      如果需要对对数据库进行大量数据更新,使用循环多次操作更新是比较浪费性能的,对于这种场景,我们可以使用addBatch()方法来收集SQL,并使用executeBatch()方法将收集的SQL批次更新,例如:

Statement stmt = conn.createStatement();
while(someCondition) {stmt.addBatch("INSERT INTO ...");
}
stmt.executeBatch();

转载于:https://my.oschina.net/u/197668/blog/361260

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

验证码识别笔记(二)

这是验证码识别的第二篇,先看一下样图吧,就是下面那张。 看到这张图片,直观上就知道比第一篇中的要简单,这个“简单”用语言来描述,可以得到下面的几条结论: 1. 图片中的字符边界比较清晰,并且单…

centos6.5下搭建oracle 11g

为什么80%的码农都做不了架构师?>>> 安装依赖 yum install binutils compat-libstdc-33 compat-libstdc-33.i686 \ elfutils-libelf elfutils-libelf-devel gcc gcc-c glibc glibc.i686 \ glibc-common glibc-devel glibc-devel.i686 glibc-headers ksh…

JS 学习笔记--11---内置对象(Global/Math)

练习中使用的浏览器是IE10,如果各位朋友有不同意见或者遇到浏览器不兼容问题,希望指正 1、内置对象的定义:有ECMAScript实现提供的、不依赖与宿主环境的对象,在ECMAScript运行之前就已经创建好的对象就叫做内置对象。就是说&…

SQL Server 视图设计器

SQL Server 中经常需要写一些查询,关联好多张表,显示无数个列。如果使用视图设计器,可以大大提高效率,同是减少差错。1. 启动视图设计器为数据库“新建视图”,将启用视图设计器。2. 添加表在起始界面,将出现…

misc类设备驱动1——板载蜂鸣器驱动测试

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、驱动部分 1、前言 九鼎移植的内核已经提供了蜂鸣器驱动源码(在SI中搜索关键字buzzer,发现出现有x210-buzzer.c文件;或者在make menuconfig界面搜索buzzer&am…

github和git@osc提交问题

为什么80%的码农都做不了架构师?>>> 今天想用gitosc push下测试下自己能否正常使用gitosc的git仓库的,公钥SSH 已经加好。 ssh -T gitgit.oschina.net 测试正常。 结果报错could not read Username for https://git.oschina.net: No such fi…

怎样跟踪来访用户?

某些监视方法是比较容易想到的,比如,当你登录网站的时候,它就可以知道你是谁了。但是这些网络监视系统是如何通过你的上网行为记录你的个人信息呢? 广告系统经常通过追踪用户行为的方法来建立用户信息库,以定位谁是目标…

【百度地图API】如何制作班级地理通讯录?LBS通讯录

原文:【百度地图API】如何制作班级地理通讯录?LBS通讯录摘要:班级通讯录必备的功能,比如人员列表,人员地理位置标注,展示复杂信息窗口,公交和驾车等。一般班级人员都不会超过300个,因为可以高效…

开发板——在X210开发板上进行裸机开发的流程

流程总结 本文以“LED流水灯”为例,说明在X210开发板上进行裸机开发的流程。 步骤一:搭建嵌入式Linux开发环境 在虚拟机中安装与配置Linux系统,并安装交叉编译工具链; 在win主机上安装dnw软件、九鼎烧写SD卡软件等内容。 步骤二&a…

zmail邮件系统安装手册 V2.0版本

2019独角兽企业重金招聘Python工程师标准>>> Tmail邮件系统安装手册 V2.0版本 1、系统环境 centos6.0以上,最小化安装(64位系统) 2、部署 1、删除自带的postfix、mysql、httpd # rpm -qa|grep postfix|xargs rpm -e --nodeps # rpm -qa|grep mysql|xargs…

Cassandra1.2文档学习(5)—— Snitch

参考资料:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/architecture/architectureSnitchesAbout_c.html#concept_ds_c34_fqf_fk 一个snitch(告密者)决定应当从哪个数据数据中心和机架写入和读取数据。…

Entity Framework在WCF中序列化的问题(转)

问题描述 如果你在WCF中用Entity Framework来获取数据并返回实体对象,那么对下面的错误一定不陌生。 接收对 http://localhost:5115/ReService.svc 的 HTTP 响应时发生错误。这可能是由于服务终结点绑定未使用 HTTP 协议造成的。 这还可能是由于服务器中止了 HTTP …

【iHMI43 4.3寸液晶模块】demo例程(版本1.03)发布

技术论坛:http://www.eeschool.org 博客地址:http://xiaomagee.cnblogs.com 官方网店:http://i-board.taobao.com 银杏科技 GINGKO TECH. 保留权利,转载请注明出处 一、简介: 1、iHMI43 演示程序(版本号:1…

SDRAM——X210的SDRAM的初始化

以下内容源于朱友鹏嵌入式课程的学习与整理,如有侵权请告知删除。 参考博客:s5pv210——初始化SDRAM - biaohc - 博客园 这里说的SDRAM,简单点理解就是内存。 一、SDRAM的简介 1、SDRAM的含义 SDRAM是Syncronized Dynamic Ramdam Access Me…

单独一台机器测试Open×××加密隧道的问题和解决

其实这篇文章和Open的关系倒不是很大,只是通过Open测试时暴露出的问题。这篇文章里面倒是包含了很多IP路由以及conntrack的细节内容。 有时候,为了节省机器,我希望在一台设备上模拟多个设备,当然,使用网络命名空…

SCRT中只换行不回车的问题(阶梯)

转载源:SecureCRT中只换行不回车的问题 - 知乎 在SecureCRT中有时会遇到由于Windows的换行和Unix的换行控制字符不同的问题(\r\n-\n),导致显示如下图所示的“阶梯”,又不想到源码中一个个改控制字符,此时可…

开发板——X210开发板的软开关(供电置锁)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、前言 本章节在裸机课程的SD卡启动部分。 本文讲述如何设置开发板,使得一按下电源键程序运行后即可松手不会断电,即供电置锁。 二、软开关的简介 电路设计一般使用拨码开…

国产Linux软件

为什么80%的码农都做不了架构师?>>> 本页面收集支持deepin/Linux的国产软件,对于每款软件以“日出东方-发行时间较短;正当壮年-时间较长且稳定;每况愈下-你们懂的”评价 软件版本时间评价有道词典 Linux版1.02015-03…

QGLViewer 编译安装步骤

由于工作学习的需要,要用opengl绘制显示些模型动画,原来用的是Qt做UI,直接调用的是QGLWidget类,但这个只是提供了基本的框架,很多交互操作还需添加代码完成,自己偷懒也觉得繁琐,就借用了开源的工…

LED——S5PV210的LED的理论与操作

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、LED物理特性介绍 LED本身有2个接线点,一个是LED的正极,一个是LED的负极。 LED的功能就是亮或者不亮,只需要给LED的正极加电压即可点亮LED,去掉电压…