什么是脏读,不可重复读,幻读

1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

2. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。

3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。

补充 : 基于元数据的 Spring 声明性事务 :

Isolation 属性一共支持五种事务设置,具体介绍如下:

l          DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .

l          READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )

l          READ_COMMITTED  会出现不可重复读、幻读问题(锁定正在读取的行)

l          REPEATABLE_READ 会出幻读(锁定所读取的所有行)

l          SERIALIZABLE 保证所有的情况不会发生(锁表)

不可重复读的重点是修改 :
同样的条件 ,   你读取过的数据 ,   再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 ,   第 1 次和第 2 次读出来的记录数不一样

再想了想,其实你后面说的都没错,唯一的问题是“数据库不会处理并发操作”这个理解所引发的,数据库不是不会处理并发操作,如果它不会处理就没有加锁机制和事务隔离机制了,数据库的问题是在于它并不知道你的并发依赖关系,因此需要你告知它。数据库的并发处理控制并不依赖于Hibernate或其它数据访问层的实现机制,唯一需要的只是你要“告知它”哪里需要重点关照。

数据库默认情况下的事务管理是“已提交读取”,也就是说已经可以保证Select不会拿到脏数据(不会发生脏读----你理解错的地方);当然也可能你理解错的脏读,脏读的意思是,事务B拿到了事务A中间状态的数据,而A后来把这个整个事务回滚了,那么事务B就相当于拿到了一个实际上根本不存在的脏数据。

而不可重复读(幻读)和更新丢失的问题需要另外解决,这个你是说对了的;目前除了加锁(排他锁)和串行化隔离外,没有更好招数。

虽然你只错了一个地方,但我感觉可能你还没有理解的比较透彻,建议去找找:脏读(写-读依赖)、更新丢(写-写依赖)、幻读(读-写依赖)这几个东西的概念,最好能自己举例说明。

分类: mysql 2010-09-13 14:11 761人阅读 评论(0) 收藏 举报

以下实验仅在MYSQL 5.0.45做的实验.

方法1:用mysql命令锁住表.

  1. public void test() {
  2. String sql = "lock tables aa1 write";
  3. // 或String sql = "lock tables aa1 read";
  4. // 如果想锁多个表 lock tables aa1 read ,aa2 write , .....
  5. String sql1 = "select * from aa1 ";
  6. String sql2 = "unlock tables";
  7. try {
  8. this.pstmt = conn.prepareStatement(sql);
  9. this.pstmt1 = conn.prepareStatement(sql1);
  10. this.pstmt2 = conn.prepareStatement(sql2);
  11. pstmt.executeQuery();
  12. pstmt1.executeQuery();
  13. pstmt2.executeQuery();
  14. } catch (Exception e) {
  15. System.out.println("异常" + e.getMessage());
  16. }
  17. }

一、对于read lock 和 write lock官方说明:
   1.如果一个线程获得一个表的READ锁定,该线程(和所有其它线程)只能从该表中读取。
      如果一个线程获得一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。
      其它的线程被阻止,直到锁定被释放时为止。

2.当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。
      虽然使用LOCKTABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。
      同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,
      在此情况下,您必须分别获得对每个别名的锁定。

二、对与read lock 和 write lock个人说明:
    1.read lock 和 write lock 是线程级(表级别).
    2.在同一个会话中加了read lock锁. 只能对这个表进行读操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
       但是在不同会话中,只能对加了read lock的表进行读操作.但可以对read lock以外的表进行增、删、改、查的操作.
    3.在同一个会话中加了write lock锁.只能对这个表进行读、写操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
      但是在不同会话中,无法对加了write lock的表进行读、写操作.但可以对write lock以外的表进行增、删、改、查的操作.
   4.如果表中使用了别名.(SELECT * FROM aa1 AS byname_table)
      在对aa1加锁时,必须把别名加上去(lock tables aa1 as byname_table read)
      在同一个会话中.必须使用别名进行查询.
      在不同的会话中.可以不需要使用别名进行查询.
   5.在多个会话中可以对同一个表进行lock read操作.但不能在多个会话中对同一个表进行lock write操作(这些锁将等待已锁的表释放自身的线程锁)
     如果多个会话对同一个表进行lock read操作.那么在这些会话中,也只能对以锁的表进行读操作.
   6.如果要你锁住了一个表,需要嵌套查询.你必须使用别名,并且,要锁定别名.
     例如.lock table aa1 read ,aa1 as byname_table read;
     select * from aa1 where id in (select * from aa1 as xx  where id=2);  
   7.解锁必须用unlock tables;

另:
      在JAVA程序中,要想解锁,需要调用 unlock tables来解锁.
      如果没有调用unlock tables.
      关闭connection 、程序结束 、调用GC 都能解锁.

方法2:用记录锁锁表.

  1. public void test() {
  2. String sql = "select * from aa1 for update";
  3. // select * from aa1 lock in share mode;
  4. try {
  5. conn.setAutoCommit(false);
  6. this.pstmt = conn.prepareStatement(sql);
  7. pstmt.executeQuery();
  8. } catch (Exception e) {
  9. System.out.println("异常" + e.getMessage());
  10. }
  11. }

1.for update 与 lock in share mode 属于行级锁和页级锁

2.for update 排它锁,lock in share mode 共享锁

3.对于记录锁.必须开启事务.

4.行级锁定事实上是索引记录的锁定.只要是用索引扫描的行(或没索引全表扫描的行),都将被锁住.

5.在不同的隔离级别下还会使用next-key locking算法.即所扫描的行之间的“间隙”也会也锁住(在Repeatable read和Serializable隔离级别下有间隙锁).

6.在mysql中共享锁的含义是:在被共享锁锁住的行,即使内容被修改且并没有提交.在另一个会话中依然看到最新修改的信息.

在同一会话中加上了共享锁.可以对这个表以及这个表以外的所有表进行增、删、改、查的操作.

在不同的会话中.可以查到共享锁锁住行的最新消息.但是在Read Uncommitted隔离级别下不能对锁住的表进行删,

改操作.(需要等待锁释放才能操作...)
                     在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
                     在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
                     在Serializable隔离级别下不能对锁住行进行增、删、改操作.  (需要等待锁释放才能操作...)

7.在mysql中排他锁的含义是:在被排它锁锁住的行,内容修改并没提交,在另一个会话中不会看到最新修改的信息。

在不同的会话中.可以查到共享锁锁住行的最新消息.但是Read Uncommitted隔离级别下不能对锁住的表进行删,

改操作.(需要等待锁释放才能操作...)
                     在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
                     在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
                     在Serializable隔离级别下不能对锁住行进行增、删、改操作. (需要等待锁释放才能操作...)

8.在同一个会话中的可以叠加多个共享锁和排他锁.在多个会话中,需要等待锁的释放.

9.SQL中的update 与 for update是一样的原理.

10.等待超时的参数设置:innodb_lock_wait_timeout=50 (单位秒).

11.任何可以触发事务提交的命令,都可以关闭共享锁和排它锁.

JAVA程序对MYSQL数据库加锁实验的更多相关文章

  1. java jdbc 连接mysql数据库 实现增删改查

    好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...

  2. JSP 实现 之 调用java方法实现MySQL数据库备份和恢复

    package cn.qm.db; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOEx ...

  3. 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...

  4. Java程序向MySql数据库中插入的中文数据变成了问号

    找到mysql的安装目录,修改my.ini文件 (1)如何找到my.ini文件 如果my.ini文件不在MySQL的安装目录下,可能放在隐藏目录,要先去找到ProgramData,(这里要先打开显示隐 ...

  5. Java中连接MySql数据库的例子

    Java中连接MySql数据库的例子: package com.joinmysql.demo; import java.sql.DriverManager; import java.sql.Resul ...

  6. JDBC Java 程序从 MySQL 数据库中读取数据,并备份到 xml 文档中

    MySQL 版本:Server version: 5.7.17-log MySQL Community Server (GPL) 相关内容:JDBC Java 程序从 MySQL 数据库中读取数据,并 ...

  7. java远程备份mysql数据库关键问题(限windows环境,亲测解决)

    其它环境同理也可解决. 条件:为了使用mysql命令,本机要安装mysql ,我本机安装的是mysql 5.5. 错误1:使用命令 mysqldump -h192.168.1.50 -u root - ...

  8. Java连接Oracle/MySQL数据库教程

    一.下载 oracle java驱动下载地址:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090 ...

  9. Java基础86 MySQL数据库基础知识

    本文知识点(目录): 1.MySQL数据库的概述    2.MySQL数据库的管理[对数据库的操作](查询.删除.创建数据库,以及查询和修改数据库的编码模式)    3.表的管理[对数据库 表的操作] ...

随机推荐

  1. 基于 DirectX11 的 MMDViewer 03-渲染管线

    准备工作: 开始搭建框架之前,你需要确保已经进行了 D3D 开发环境的搭建,相关教程可以阅读这篇文章.不了解 DirectX11 的人,这个作者有关 DirectX11 的教程最好阅读一下,虽然文章不 ...

  2. javascript常见方法汇总之一——数组字符串相关

    (转载至慕课网) 原文链接:https://www.imooc.com/article/46933 github地址:https://github.com/dorseysen/notes-about- ...

  3. java第三方类库实现图片等比缩放

    public class ThumbnailTest { public static void main(String[] args) { InputStream is = null; try { / ...

  4. EF中关系映射问题

    一对一,和一对多的简单问题就部说了,直接来多对多这样的问题吧. 首现关系映射为这样的: /// <summary> /// 对应数据库中dbo.Address表 /// </summ ...

  5. SPI子系统分析之三:驱动模块

    内核版本:3.9.5 SPI核心层(平台无关) SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下. 下列函数位 ...

  6. 前端开发之JavaScript HTML DOM理论篇一

    主要内容: 1.DOM简介 2.DOM 节点 3.DOM 方法和属性 4.DOM 访问和修改 一.DOM简介 1.什么是 DOM? DOM 是 W3C(万维网联盟)的标准. DOM 定义了访问 HTM ...

  7. Mono在Full AOT模式下的限制

    [Mono在Full AOT模式下的限制] 调试时遇到一个Mono运行时异常: ExecutionEngineException: Attempting to JIT compile method ' ...

  8. Python_12-线程编程

    1.1    Python中的线程使用1.1.1 函数式1.2    创建threading.Thread的子类来包装一个线程对象1.2.1 threading.Thread类的使用1.3    线程 ...

  9. Spring Data Jpa使用@Query注解实现模糊查询(LIKE关键字)

    /** * * @param file_name 传入参数 * @return */ @Query(value = "select * from user where name LIKE C ...

  10. 更改IDEA高亮字体背景颜色

    IDEA工具中依次进入file -> settings -> editor -> colors Scheme -> general,在右侧窗口中将result.i  都改成自己 ...