事务是一组原子性的SQL查询语句,也可以被看做一个工作单元。如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都不会执行。也就是说,事务内的语句要么全部执行,要么一句也不执行。

事务的特性:acid,也称为事务的四个测试(原子性,一致性,隔离性,持久性)

automicity:原子性,事务所引起的数据库操作,要么都完成,要么都不执行

consisitency:一致性,事务执行前的总和和事务执行后的总和是不变的

isolation:隔离性, 某个事务的结果只有在完成之后才对其他事务可见

durability:持久性,一旦事务成功完成,系统必须保证任何故障都不会引起事务表现出不一致性

事务的状态:

活动

部分提交

失败

中止

提交

事务在某一时刻,一定处于上边五种状态中的一种,事务各状态之间的转换如下所示:

事务并发导致的问题

脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新了原有的数据。

幻读(Phantom Read):在一个事务的两次查询中数据不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

并发控制

多版本并发控制: Multiversion concurrency control,MVCC

每个用户操作数据时都是源数据的时间快照,当用户操作完成后,依据各快照的时间点在合并到源数据中

锁:要想实现并发控制,最简单的实现机制就是锁(MVCC采用的不是锁机制)。

读锁:共享锁,由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写

写锁:独占锁,由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁

锁粒度:从大到小,MySQL服务器仅支持表级锁,行锁需要存储引擎完成。

表锁:锁定某个表

页锁:锁定某个页

行锁:锁定某行

粒度越精细,并发性越好。即行锁的并发性最好,但需要存储引擎的支持。

事务的四种隔离级别

读未提交(read uncommitted): 允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

读提交(read committed): 只能读取到已经提交的数据。oracle等多数数据库默认都是该级别

可重读(repeatable read): 在同一个事务内的查询都是事务开始时刻一致的,innodb的默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读

可串行(serializable): 完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

在MySQL中,在并发控制情况下,不同隔离级别分别有可能产生问题如下所示:

上边之所以介绍那么多理论知识,是为了便于理解。在上边的表格中已经列出来了,在不同隔离级别下,数据的显示效果可能出现的问题,现在在linux上安装好mysql,通过我们的实验来一起看一下在不同隔离级别下数据的显示效果吧。

实验环境:

linux系统:RedHat 5.8

linux内核:linux-2.6.18-308.el5

mysql版本:mysql-5.6.10-linux-glibc2.5-i686

本次实验的所有操作均在虚拟机中完成,通过Xmanager连接虚拟机,然后打开两个会话连接,在两个会话中,同时更改隔离级别,然后查看数据的显示效果。

本次实验中mysql采用源码编译安装的方式安装mysql,你也可以使用rpm包的方式直接安装mysql。具体源码安装的方式及过程,这里不再演示,在前面的博客中,我已经介绍了很多次。如果你采用源码编译安装的方式,不知道如何安装mysql,可参看我以前写的博客,里边都有介绍。采用源码编译安装的方式,在mysql的配置文件中,最好启用每表一个表空间。这里我们直接启用。

因为是实验,这里没有对mysql设置密码,因此,我们直接使用命令进入mysql。命令及显示效果如下:

50[root@mysql ~]# mysql -uroot -p #使用该命令进入mysql,因为没有设置密码,在要求输入密码时直接按回车键即可

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 2

Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%iso%'; #查看mysql默认的事务隔离级别,默认为可重读。也可以使用select @@tx_isolation命令查看

+-----------------+------------------+

| Variable_name | Value |

+-----------------+------------------+

| tx_isolation | REPEATABLE-READ |

+-----------------+------------------+

1 row in set (0.36 sec)

mysql> show databases; #查看系统已经存在的数据库

+---------------------+

| Database |

+---------------------+

| information_schema |

| mysql |

| performance_schema |

| test |

+---------------------+

4 rows in set (0.00 sec)

现在导入我们实验所使用的数据库。

[root@mysql ~]# mysql < jiaowu.sql #导入实验所用的jiaowu数据库

[root@mysql ~]# mysql -uroot -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 7

Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases; #查看导入的jiaowu数据库是否存在

+----------------------+

| Database |

+----------------------+

| information_schema |

| jiaowu |

| mysql |

| performance_schema |

| test |

+----------------------+

5 rows in set (0.01 sec)

我们在mysql命令界面下,没有明确启用事务时,输入的每个命令都是直接提交的,因为mysql中有个变量的值,可实现自动提交。也就是说我们每输入一个语句,都会自动提交,这会产生大量的磁盘IO,降低系统的性能。在我们做实验时,因为我们要明确使用事务,所以,建议关闭自动提交的功能,如果不关闭也没有关系,但是如果你没有明确使用事务,想要做下边的实验,那就需要关闭此功能了。这里,我们明确使用事务,且关闭自动提交功能。假如你关闭了自动提交功能,需明确使用事务,否则你输入的所有语句会被当成一个事务进行处理。命令如下:

16mysql> select @@autocommit; #查看该值,为1表示启动自动提交

+--------------+

| @@autocommit |

+--------------+

| 1 |

+--------------+

1 row in set (0.00 sec)

mysql> set autocommit=0; #关闭自动提交功能

Query OK, 0 rows affected (0.00 sec)

mysql> select @@autocommit; #重新查看该值,为0表示关闭自动提交功能

+--------------+

| @@autocommit |

+--------------+

| 0 |

+--------------+

1 row in set (0.00 sec)

现在打开两个会话,在这两个会话中分别进入mysql,首先记得要就修改两个回话中的autocommit变量,关闭自动提交功能,然后查看事务的隔离级别,默认为REPEATABLE-READ。在两个会话中都需要修改隔离级别。我们先从最低的隔离级别开始演示。

30mysql> select @@tx_isolation;

+-------------------+

| @@tx_isolation |

+-------------------+

| REPEATABLE-READ |

+-------------------+

1 row in set (0.00 sec)

mysql> set tx_isolation='read-uncommitted'; #修改隔离级别,将隔离级别可重读改为读未提交

Query OK, 0 rows affected (0.00 sec)

mysql> select @@tx_isolation;

+-------------------+

| @@tx_isolation |

+-------------------+

| READ-UNCOMMITTED |

+-------------------+

在两个回话中,修改完隔离级别后,使用导入的数据库,用tutors表来验证显示效果。

mysql> use jiaowu; #使用jaiowu数据库

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables; #查看该数据库中都有那些表

+-------------------+

| Tables_in_jiaowu |

+-------------------+

| courses |

| scores |

| students |

| tutors |

+-------------------+

4 rows in set (0.00 sec)

在会话1中,我们来修改tutors中的数据,在会话2中我们来查看数据,看会是什么情况。本打算使用tutors表来演示下边的实验,但修改完数据截图时比较麻烦,所以,自己就写了个脚本,比着tutors表的各字段创建了一个新表teachers。脚本写的有点拙劣,有兴趣可自己动手写个更好的脚本来实现创建及插入数据。创建表及插入数据的脚本如下:

23#!/bin/bash

#

#Author: hulunbeier, http://lq2419.blog.51cto.com/

#Description: creating table and inserting data

#

let B=0

mysql -e "use jiaowu;create table teachers like tutors;"

read -p "Input a number to create NUMBER data. You choice : " NUM #执行该脚本是,会让输入一个数字,因为是实验,所以我们这里进插入5行数据,读者可自行修改

for I in `seq 1 $NUM`; do

NAME=tech$I

A=`echo $RANDOM/365 | bc`

until [ $A -ge 40 ] && [ $A -le 100 ]; do

A=`echo $RANDOM/365 | bc`

done

B=`echo $RANDOM%2 | bc`

if [ $B = 0 ]; then

GD=F

else

GD=M

fi

mysql -e "insert into jiaowu.teachers (Tname,Gender,Age) values ('$NAME','$GD',$A);"

echo "create tech$I success."

done

执行上边的脚本即可创建相应表及插入数据。查看下我们创建的新表是否成功,里边是否有数据。查询命令及显示结果如下所示:

创建的新表已经存在,且插入数据也已成功,现在我们就用teachers表来演示以下各实验。演示实验从低隔离级别开始,到高隔离级别结束。

Read-uncommitted:读未提交

首先,修改两个会话中的自动提交功能,将其关闭,然后修改系统默认的隔离级别,从低级别开始,将默认的可重读改为读未提交。

以上修改在两个会话中完成后,我们明确启动事务,查询下表中的所有数据信息,显示TID为5的老师的年龄为61,然后在会话1中更新teachers表中TID为5的老师的年龄,将原来的61改为50,接着,在两个会话中在重新查询下所有的数据,看TID为5的老师的年龄是多少。命令及显示效果如下所示:

当我们在会话1中使用rollback回滚之后,再在两个会话中查看数据,发现还是61。从上边两个会话的显示效果,可以看到,在隔离级别为读未提交时,当我们开启一个事务时,在该事务中修改了某个数据行的信息,且在该事务中,并未提交,但在另一个事务中,如果都是对同一个数据集的操作,会发现我们前后两次查询的结果不一样了,在同一个事务中,两次查询得到的结果不一样,这种情况是不允许出现。此时就出现了脏读、不可重复读及幻读的现象。

Read-committed:读提交

首先在上边修改的基础上再次修改隔离级别,将读未提交改为读提交。然后,我们还去修改TID为5的老师的年龄,将61改为40。接着,在两个会话中再次查看显示效果。命令及显示效果如下所示:

现在,在会话1中,我们使用commit命令提交事务,然后再会话2中,查看下显示效果,看又是怎么样的。结果会发现,在会话2中,TID为5的老师的年龄变成了40。从上边的显示效果,会发现,当隔离级别为read-committed(读提交)时,当我们在会话1中开启事务,并修改了某一行数据的信息时,在会话1中可以看到修改后的效果,但在会话2中并不会看到修改后的结果。当我们在会话1中提交事务后,在再会话2中查询,会发现,跟我们上次查询的不一样了,显示的是会话1修改后的结果。在该隔离级别下,虽然可以避免脏读的现象发生,但还是会出现不可重复读和幻读的现象。

Repeatable-read:可重读

首先修改隔离级别,将读提交改为可重读。然后,在会话1中,依然修改TID为5的老师的年龄,将其年龄改为60。最后,两个会话中再来查看结果。

从上边的显示结果会发现,在该隔离级别下,当我们在会话1中修改了某个值时,会话1会立即显示修改后的结果,而会话2中不会显示。当我们在会话1中提交事务后,得到永久结果,在会话1中在查看,还是修改后的结果,但在会话2中,还是原来的结果。但当我们在会话2中提交事务后,再来查询,发现是会话1中修改后的结果,在会话2中,我们没做任何修改,我一提交事务,发现,数据竟然变了。起码,事务提交前和提交后看到的数据是不一样的。此时就出现了幻读的现象。

Serializable:可串行

首先,我们依然修改隔离级别,将可重读改为可串行。然后再会话1中,启动事务,并将TID为5的老师的年龄由60改为100,然后,在会话1和2中查看。在没有启动事务前,我们先来看下TID为5的老师年龄是多少。

在上边的显示效果中,发现,在可串行隔离级别下,当我们启动两个事务时,如果在其中一个事务中,修改了某个数据行,在另一个事务中,我们是无法查询到该数据集的信息的,也就是说系统不会显示出任何信息,除非在修改的事务中,我们提交了,或者是执行了rollback命令。假如在修改的事务中,我们既没有执行commit命令提交,也没有执行rollback命令回滚,那么,在另一个事务中,当我们查询时,会一直卡着不动,直到锁时间超时,然后提示我们重新开启事务。在上图中,发现,在会话1中,当我们启动一个事务,并修改了一个数据后,在会话2中,我们是不能查询到任何信息的,当我们在会话1中执行了rollback命令后,会话2中才会显示查询结果,此时的查询所用时间会比以前查询所用时间长很多。因为在可串行级别下,是不允许通知开启多个事务的,或者说是不允许对同一个数据集执行任何操作的。此时,既不会出现脏读、不可重复读,也不会出现幻读现象。但是此时的并发性会受影响。

综上所述,在低隔离级别下,当有多个事务并发执行时,虽然会产生很多问题,如脏读、不可重复读、幻读等现象,但事务的并发性较好,可同时执行多个事务;在高隔离级别下,当有多个事务并发执行时,因在高隔离级别下,不支持多事务并发执行,虽然不会出现诸如脏读、不可重复读及幻读等现象,但并发性较低。InnoDB默认的隔离级别是repeatable-read(可重读),而在大多数的数据库中,oracle等多数数据库,一般默认的隔离级别是read-committed(读提交)。一般来说在实际应用中,除了在银行、股票等对数据安全要求较高的场景外,必须使用较高隔离级别外,其他对数据要求不高的场合,可采用低隔离级别,以提高并发性。然而,究竟哪种隔离级别更适合,那就需要看你对数据的安全性要求有多高了。

原文:http://www.haofanben.com/jiaocheng/mysqlshujuku/197015.html

mysql不同连接的事务_mysql中不同事务隔离级别下数据的显示效果--转载相关推荐

  1. mysql中不同事务隔离级别下数据的显示效果--转载

    事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...

  2. mysql mvcc和行锁_mysql在RR的隔离级别下,究竟是通过MVCC解决幻读的还是通过行锁的next key算法解决的?...

    首先,我们需要搞懂几个隔离级别的意思和每个隔离级别会出现的问题.隔离级别分为:读未提交,读提交,可重复读和可串行化. 读未提交是最低级别的隔离级别,表示当一个事务还没有提交时,他所做的变更就被别的事务 ...

  3. mysql可重复读 加锁_mysql可重复读隔离级别加锁分析

    问题 myql可重复读隔离级别下可能会导致插入阻塞,问题复现如下 表中有3列都是int类型 其索引情况如下: id为主索引,c,d为普通索引 现在开始制作问题: 在这里我分别开启两个事务:第一个事务中 ...

  4. mysql中的事务_mysql中的事务,你理解嘛?

    事务又叫做TCL,全称是transaction control language,意思是事务控制语言.这篇文章还是属于我的mysql基础文章,在前面我们介绍了下面这些基础知识: 1.数据库的增查改删操 ...

  5. mysql内连接和交叉连接_MySQL中的内连接、外连接、交叉连接

    内连接(INNER JOIN): 分为三种 等值连接.自然连接.不等连接 外连接(OUTER JOIN): 左外连接(LEFT OUTER JOIN或LEFT JOIN) 右外连接(RIGHT OUT ...

  6. mysql索引commit卡死_mysql 5.6 read-committed隔离级别下并发插入唯一索引导致死锁一例...

    今天,某个环境又发生了死锁,如下: *** (1) TRANSACTION: TRANSACTION 735307073, ACTIVE 0 sec inserting mysql tables in ...

  7. Mysql在可重复读事务隔离级别下怎么解决幻读的

    目录 前言 并发事务产生的问题 更新丢失 回滚丢失 覆盖丢失 脏读 不可重复读 幻读 快照读和当前读 幻读验证 快照读如何避免幻读 当前读如何避免幻读 可重复读隔离级别发生幻读情况 小结 前言 Mys ...

  8. MySQL事务的四种隔离级别,mysql中的不可重复读和幻读的区别,Repeatable read可重复读隔离级别下怎么不存在幻读问题?

    1. 事务的隔离级别 1.1 read uncommited:读未提交.一个事务读到了另一个事务未提交的脏数据,称之为脏读. 1.2 read commited:读已提交.解决了脏读问题,但当前事务两 ...

  9. mysql特性举例_MySQL事务的四大特性和隔离级别

    1.事务的四大特性(ACID) #### 1.1.原子性(Atomicity) 原子性是指事务包含的一系列操作要么全部成功,要么全部回滚,不存在部分成功或者部分回滚,是一个不可分割的操作整体. 1.2 ...

最新文章

  1. java 之 运算符
  2. Rdd没法调用toDF原因
  3. 教你玩转CSS margin(外边距)
  4. NHibernate从入门到精通系列(5)——持久对象的生命周期(下)
  5. 解决办法:自动挂载失效,VirtualBox共享文件夹给Ubuntu虚拟机
  6. 基于钉钉服务简单监控
  7. 提取unity3d游戏资源文件
  8. 一个简单LEGv8处理器的Verilog实现【三】【工具使用和编程规范】
  9. FileUpload类中FileUpload1.FileName和FileUpload1.PostedFile.FileName的区别
  10. 线性代数 --- 线性代数中的一些特殊矩阵(被广泛用于高斯消元法的消元矩阵E)(个人笔记扫描版)
  11. 数据分析师工资水平怎么样?看看这些你就知道了
  12. 计算机内存不足黑屏怎么办,win10内存不足会黑屏怎么办
  13. 无限极分类之查找家谱树
  14. Android12(S)授权弹窗被悬浮窗遮挡导致无法点击问题分析
  15. Hadoop退出安全模式
  16. AGM AG16K FPGA介绍
  17. 用学号、姓名查询学生信息python
  18. 基于java+SpringBoot+HTML+Mysql音乐网站
  19. matlab 2012a mex设置,【mex成功但compile failed】:win7 64bit matlab R2012a mex问题
  20. Kubernetes 集群仓库 Harbor Helm3 部署

热门文章

  1. css3自定义checkbox radio的样式
  2. LOGO SEO 优化
  3. Error:(27, 17) java: 找不到符号 符号: 类 Role 位置: 类 net.togogo.bean.User
  4. JS常见加密 AES、DES、RSA、MD5、SHAI、HMAC、Base64(编码) - Python/JS实现
  5. int 类型数据的最大值,最小值及其十六进制表示方式
  6. java 继承 ppt_理论五继承_JAVA学习课件_ppt_大学课件预览_高等教育资讯网
  7. php closewait,CLOSE_WAIT问题终于解决了。
  8. lua语言入门学习(四)项目初体验之抽奖转盘(1)
  9. webrtc示例peerconnection_clientserver
  10. XP下卸载WINDOWS7