第十章 事务(Transactions)

事务用于在并发访问期间提供数据完整性,正确的应用程序语义和一致的数据视图。 需要所有JDBC兼容驱动程序来提供事务支持。 JDBC API中的事务管理反映了SQL:2003规范,并包含了这些概念

  • 自动提交模式
  • 事务隔离级别
  • 保存点

本章介绍与单个Connection对象关联的事务语义。 涉及多个Connection对象的事务在第12章“分布式事务”中讨论。

10.1 交易界限和自动提交

什么时候开始一个新的事务是由JDBC驱动程序或底层数据源隐含的决定,虽然一些数据源实现了一个明确的“begin transaction”语句,但是没有JDBC API可以实现,通常,当当前的SQL语句需要一个并且没有事务已经存在的时候,一个新的事务被启动。 一个给定的SQL语句是否需要一个事务也由SQL:2003指定。

Connection属性auto-commit指定何时结束事务。 一旦该语句完成,启用自动提交会在每个单独的SQL语句之后导致事务提交。 一个语句被认为是“完成”的点取决于SQL语句的类型以及应用程序在执行它之后执行的操作:

  • 对于“数据操作语言”(DML)语句(如“插入”,“更新”,“删除”和“DDL”语句),语句在执行完毕后立即完成
  • 对于Select语句,当关联的结果集关闭时,该语句将完成。
  • 对于CallableStatement对象或返回多个结果的语句,当所有关联的结果集都已关闭时,该语句已完成,并且已检索所有更新计数和输出参数

10.2 禁用自动提交模式

当禁用自动提交时,每个事务必须通过调用Connection方法提交或通过调用Connection方法回滚来显式回滚来显式提交。 这适用于在驱动程序上方的层中进行事务管理的情况,例如

  • 当应用程序需要将多个SQL语句组合成一个事务
  • 当事务由应用程序服务器管理时

默认值是在创建Connection对象时启用自动提交模式。 如果自动提交的值在事务中间更改,则提交当前事务。 如果调用了setAutoCommit,并且auto-commit的值不会从当前值更改,则被视为无操作
如第12章“分布式事务”所述,为参与分布式事务的连接启用自动提交是一个错误。

10.2 事务隔离等级

事务隔离级别指定事务中的语句“可见”哪些数据。 它们通过定义在相同目标数据源之间的交易之间可以进行什么交互(如果有的话)直接影响并发访问级别。 并发事务之间的可能交互分类如下:

  • 当允许事务查看未提交的数据更改时,会发生脏读。 换句话说,交易之前所做的更改在提交之前在事务外部可见。 如果更改回滚而不是提交,则可以根据不正确的临时数据完成其他事务的工作。
    不可重复读取时发生:
    1.事务A读取一行
    2.事务B更改行
    3,事务A第二次读取相同的行并获得不同的结果

  • 幻象读取发生时
    1.事务A读取满足WHERE条件的所有行
    2.事务B插入一个满足相同条件的附加行
    3.事务A重新评估WHERE条件并拾取附加的“幻像”行

JDBC通过添加TRANSACTION_NONE来增强 SQL:2003定义的四个级别的事务隔离。 从最少限制到最严格的交易隔离级别是:
1,TRANSACTION_NONE :表示驱动程序不支持事务,这意味着它不是JDBC兼容的驱动程序。
2,TRANSACTION_READ_UNCOMMITTED:允许事务查看未提交的数据更改。 这意味着脏的读取,不可重复的读取和幻像读取是可能的
3,TRANSACTION_READ_COMMITTED:意味着事务之前进行的任何更改在事务发生之前都不可见,直到事务被提交。 这样可以防止脏读,但是不可重复的读取和幻像读取仍然是可能的。
4,TRANSACTION_REPEATABLE_READ:不允许脏读和不可重读读。 幻影读取仍然是可能的。
5,TRANSACTION_SERIALIZABLE:指定防止脏读,不可重复读取和幻像读取。

10.2.1 使用 setTransactionIsolation 方法

Connection对象的默认事务级别由提供连接的驱动程序决定。 通常,它是底层数据源支持的默认事务级别
提供了Connection方法setTransactionIsolation,以允许JDBC客户端更改给定Connection对象的事务隔离级别。 新的隔离级别对于会话的剩余部分或直到下一次调用setTransactionIsolation方法仍然有效

在事务中间调用setTransactionIsolation方法的结果是实现定义的

方法getTransactionIsolation的返回值应该反映实际发生时隔离级别的变化。 建议驱动程序实现setTransactionIsolation方法来更改从下一个事务开始的隔离级别。 提交当前事务以使效果立即也是有效的实现

给定的JDBC驱动程序可能不支持所有四个事务隔离级别(不计算TRANSACTION_NONE)。 如果驱动程序不支持在调用setTransactionIsolation中指定的隔离级别,则可以替换更高级别,更严格的事务隔离级别。 如果驱动程序无法替代较高的事务级别,则会引发SQLException。 DatabaseMetaData方法supportsTransactionIsolationLevel可以用于确定驱动程序是否支持给定的级别

10.2.2 性能注意事项

随着事务隔离级别的增加,需要更多的锁定和其他DBMS开销来确保正确的语义。 这反过来降低了可以支持的并发访问的程度。 因此,当应用程序使用更高的事务隔离级别时,应用程序可能会看到降低的性能。 因此,无论是应用程序本身还是应用程序服务器的一部分,事务管理器在确定哪个事务隔离级别合适时,应该对数据一致性的需求与性能要求进行权衡。

10.3 Savepoints

保存点通过标记事务中的中间点来提供对事务的更细粒度的控制。 一旦设置了保存点,事务可以回滚到该保存点,而不影响以前的工作

DatabaseMetaData.supportsSavepoints方法可用于确定JDBC驱动程序和DBMS是否支持保存点

10.3.1 设置和回滚至 保存点

Connection.setSavepoint方法可用于在当前事务中设置保存点。 如果调用了setSavePoint并且没有活动的事务,则事务将被启动。 Connection.rollback方法已被重载以获取一个保存点参数

代码示例10-2将一行插入到表中,设置保存点svpt1,然后插入第二行。 当事务稍后回滚到svpt1时,第二个插入被撤消,但是第一个插入保持不变。 换句话说,当交易被提交时,只有包含“FIRST”的行将被添加到TAB1

conn.createStatement();
int rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) VALUES " +
"(’FIRST’)");
// set savepoint
Savepoint svpt1 = conn.setSavepoint("SAVEPOINT_1");
rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) " +
"VALUES (’SECOND’)");
...
conn.rollback(svpt1);
...
conn.commit();

10.3.4 释放保存点

Connection.releaseSavepoint方法将Savepoint对象作为参数,并从当前事务中删除它和任何后续的保存点。

一旦保存点被释放,尝试在回滚操作中引用它将导致抛出SQLException。

在事务中创建的任何保存点将自动释放,并在事务提交或整个事务回滚时变为无效。

将事务回滚到保存点将自动释放并使无效的所有保存点之后创建的任何其他保存点无效

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • JDBC概述 在Java中,数据库存取技术可分为如下几类:JDBC直接访问数据库、JDO技术、第三方O/R工具,如...
    usopp阅读 3,526评论 3 75
  • 很多人喜欢这篇文章,特此同步过来 由浅入深谈论spring事务 前言 这篇其实也要归纳到《常识》系列中,但这重点又...
    码农戏码阅读 4,704评论 2 59
  • 一、JDBC简介 1、JDBC基础 JDBC(Java Database Connectivity)是一个独立于特...
    慕凌峰阅读 1,206评论 2 32
  • 我在一寸寸蔓延的山火中等你 我在一阵阵奔腾的海啸中等你 在生中爱你 在死中等你 我要住进花的子房 与你孕育又一年的...
    叶子雅舍阅读 343评论 1 1
  • 一天小猴子拿着一个大西瓜走在回家的路上!可是天天很热,他中暑了!然后就浑睡着了!这时,狐狸先生走过来了!看到睡着的...
    哈士奇2016阅读 207评论 0 0