Oracle和Mysql中的数据库事务问题:Mysql Read-Repeatable有问题

今天不知不觉想到数据库的乐观锁和悲观锁,遂想写个程序测测,却发现了另一个问题,Mysql InnoDB的Read-Repeatable事务级别使用不当会存在数据一致性问题。

如下的测试程序:

public class OptimisticAndPessimisticLockTest2 {

public static void main(String[] args) throws Exception {

//创建测试表和数据

initDatabase();

//创建两个线程同时操作同一条记录

OptimisticThread ot1 = new OptimisticThread(newConnection(), "O1");

OptimisticThread ot2 = new OptimisticThread(newConnection(), "O2");

ot1.start();

ot2.start();

}

public static Connection newConnection() throws Exception {

Class.forName("com.mysql.jdbc.Driver");

Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");

return con;

}

public static void initDatabase() throws Exception {

Connection con = newConnection();

Statement stmt = con.createStatement();

stmt.execute("drop table if exists locktest");

stmt.execute("create table locktest( name varchar(10)) ENGINE=InnoDB");

stmt.executeUpdate("insert into locktest values('XJD')");

con.close();

}

public static class OptimisticThread extends Thread {

Connection con;

String name;

public OptimisticThread(Connection con, String name) {

this.con = con;

this.name = name;

}

@Override

public void run() {

try {

//设置事务级别为可重复读

this.con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

this.con.setAutoCommit(false); //开始事务

System.out.println("Started Transaction...: " + name);

Statement stmt = this.con.createStatement();

//先查询一下是否有'XJD'的记录

ResultSet rs = stmt.executeQuery("select * from locktest where name='XJD'");

if (rs.next()) {

System.out.println("Got Record: " + name + " value: " + rs.getString(1));

}

rs.close();

Thread.sleep(5000);//暂停5s让另一个线程也查询完成

//更新'XJD'的记录

int i = stmt.executeUpdate("update locktest set name = '" + name + "' where name = 'XJD'");

System.out.println("Update Record: " + name + " count: " + i);//更新成功后i为1

Thread.sleep(5000);//暂停5s让另一个线程也作更新操作

//查询更新后的记录

rs = stmt.executeQuery("select * from locktest where name='" + name + "'");

if (rs.next()) {

System.out.println("Got Record: " + name + " value: " + rs.getString(1));

}

rs.close();

//查询原来的记录

rs = stmt.executeQuery("select * from locktest where name='XJD'");

if (rs.next()) {

System.out.println("Got Record: " + name + " value: " + rs.getString(1));

}

rs.close();

Thread.sleep(10000);

System.out.println("Commiting Transaction...: " + name);

this.con.commit();

this.con.close();

} catch (SQLException e) {

System.out.println("Exception in " + name + ": " + e);

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

输出结果:

Started Transaction...: O1

Got Record: O1 value: XJD

Started Transaction...: O2

Got Record: O2 value: XJD

Update Record: O1 count: 1

Got Record: O1 value: O1

Commiting Transaction...: O1

Update Record: O2 count: 0 //见下一行的说明

Got Record: O2 value: XJD //此处在O2线程中还可以查询到XJD记录,但前一条的Update结果却是0

Commiting Transaction...: O2

从输出结果中注释的两行可以看出,Read-Repeatable事务级别容易出现问题:

O1和O2两个线程都开启了事务--O1和O2中都可以查询到XJD的记录--O1更新并提交了XJD记录为'O1'--O2中Update语句返回0可知O2没有更新到‘XJD'的记录--但是O2中仍可使用查询语句查询到‘XJD'的记录(因为可重得读事务设置)--但此时问题就来了,我在O2中可查询到记录,为什么更新不到呢????

从上面的分析,可以看出,Read-Repeatable事务级别容易出现业务上的问题,比如我们在一个事务中查询到一条记录,而后我们对该记录进行操作,发现这些操作跟本不起作用,如果业务比较复杂,跨度大,很容易使我们“迷惑“,我们错在哪,为什么查询到了,却更新不到!!!

难怪Oracle不支持Read-Repeatable事务,在对Oracle执行:

con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

抛出异常:

java.sql.SQLException: 仅 READ_COMMITTED 和 SERIALIZABLE 是有效的事务处理级

我使用的是Mysql默认安装,发现Mysql Innodb默认使用的就是Read-Repeatable事务,所以只能说要谨慎吧!

再则对于乐观锁,可能使用版本列、时间戳列、其它列数据对比,无论是何种方式,都要在提交前先查询一次,与之前查询的数据进行某些列的对比,如果使用了Read-Repeatable事务,那么对比永远是相同的,这样乐观锁就出现问题了,不是我们想要的结果,所以在使用乐观锁时不能使用Read-Repeatable事务,而应该使用Read-Commited事务。

以上为个人见解,本人对数据库事使用不是很多,有问题之处望高人指点赐教!!!

此处附上一处乐观与悲观锁的文章:http://www.zhujiangroad.com/program/Oracle/21775.html

oracle repeatable read,Oracle和Mysql中的数据库事务有关问题:Mysql Read-Repeatable有有关问题...相关推荐

  1. 如何在mysql中录入数据库_如何向MySQL数据库的表中录入数据

    当你建好了数据库及表时,你首先想到的就是向数据库的表中输入数据.这就牵涉到如何向数据库增加数据.下面我们就来探讨一下这个问题: 1.一般我们常用的方法是insert语句(这里假定各位的版本都不是很低) ...

  2. 陆金所MySQL_独家揭秘陆金所去Oracle全过程:18个月将90%数据库业务换到MySQL

    原标题:独家揭秘陆金所去Oracle全过程:18个月将90%数据库业务换到MySQL 作者 | 田晓旭 陆金所目前已经完成全站 90% 以上的去 Oracle 工作,并且将在 6 月底前下线最后一台 ...

  3. mysql中影响数据库性能的因素讲解

    mysql中影响数据库性能的因素讲解 在本篇文章中我们给大家讲述了mysql中影响性能的因素以及相关知识点内容,有兴趣的朋友参考下 关于数据库性能的故事 面试时多多少少会讲到数据库上的事情," ...

  4. MySql中的日期处理(适用于 MySQL 5.X 及以上版本)

    MySql中的日期处理(适用于 MySQL 5.X 及以上版本) 一.日期相关函数 date_format(date, format)MySQL日期格式化unix_timestamp()str_to_ ...

  5. mysql 中show 命令用法详细介绍 mysql过程(procedure)的使用

    a. show tables或show tables from database_name; -- 显示当前数据库中所有表的名称 b. show databases; -- 显示mysql 中所有数据 ...

  6. mysql中的nan_使用python-cod将MySql列中的“NAN”值转换为NULL

    我通过python在MySql中编写/存储数据.如果MySql中的列数据包含"NAN",那么我如何处理它们.目前我知道如何处理空白或无值,但在这里我被卡住了.数据看起来像这样# f ...

  7. mysql数据库模型相应解释_数据库事务系列-MySQL跨行事务模型

    说来和MySQL倒是有缘,毕业的第一份工作就被分配到了RDS团队,主要负责把MySQL弄到云上做成数据库服务.虽说整天和MySQL打交道,但说实话那段时间并没有很深入的理解MySQL内核,做的事情基本 ...

  8. 视频教程-19全新mysql教程零基础入门实战精讲mysql视频DBA数据库视频教程SQL教程-MySQL

    19全新mysql教程零基础入门实战精讲mysql视频DBA数据库视频教程SQL教程 7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有node/ja ...

  9. 如何查询Oracle,Sql Server,MySQL 中的数据库名称、数据表名称、字段名称

    在开发项目的时候有个功能需要查看数据库中有哪些表,以及每个表有哪些字段,在网上查看了一下,现在分享给大家. Oracle: 查询数据表(Tables)名称: select Table_Name, Ta ...

最新文章

  1. 机器学习实现计算不规则图形面积_人教版小学数学五年级上册解决问题(不规则图形的面积)公开课优质课课件教案视频...
  2. 备忘: 网络订购烟草
  3. Mockito和Hamcrest的试驾制造商
  4. 窗口位置按钮取消_VBA002:“宏”的保存位置有哪几种方式?
  5. 每天一个linux命令:【转载】less命令
  6. 移动端媒体尺寸_网络推广外包浅析提升移动端网站建设效率有哪些网络推广外包技巧-企服...
  7. lamp+laravel
  8. python定义字典对象时_Python对象类型之字典
  9. 从零实现深度学习框架——实现常见运算的计算图(上)
  10. audio.js的研究与使用
  11. 吉利嘉际车机安装第三方软件教程(2022年更新)
  12. Visual Studio Code的下载与安装
  13. sublime 配置快捷键
  14. Windows问题记录之任务栏图标透明
  15. 自动控制原理3.3---二阶系统的时域分析
  16. 【高级篇 / DNS】(7.0) ❀ 03. FortiGate作为Window DNS的备用DNS服务器 ❀ FortiGate 防火墙
  17. python中使用matplotlib.pyplot画函数图像
  18. IDEA的设置(背景颜色、字体大小、注释颜色)
  19. 闪击6偏大偏小?_WEN开箱 | 开箱李宁闪击5季后赛版探讨对比普通版和闪击3怎么选...
  20. 二战考研哈工大之路记录

热门文章

  1. 短地址TinyURL的API使用
  2. java csv导出 乱码_java导出csv乱码解决方法介绍
  3. 查准率、查全率与 F1 值
  4. 欧几里得定理与扩展欧几里得
  5. 二维周期光栅结构的配置
  6. Stata+R: Stata 与 R 等效命令备忘录
  7. Python往图片写入文字,插入图片的方法
  8. h5页面手机端适配头
  9. 关于springMvc如何返回字符串而不是被当做路径跳转
  10. java 简单时钟界面_JavaFX实现简易时钟效果(一)