MySQL之事务(基本操作、ACID特性、隔离级别、脏读幻读不可重复读)

事务

数据库事务(Database Transaction) :就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们可以达到这种效果,事务还规定不用的客户端看到的数据是不相同的。

  • 通过案例来理解事务:
    A同学像B同学转账1000元
    1)A同学余额被扣款1000元
    2)B同学余额增加1000元
    上面两个步骤,如果中间任何环节没有出错,那么转账成功。但是如果第一步扣款完成后,第二步B同学没有增加1000元,此时A同学余额岂不是白扣了?所以出现了数据库事务

事务的基本操作

案例:银行转账的例子就是需要考虑事务的问题
创建测试表

mysql> create table account(
    -> id int primary key,
    -> name varchar(50) not null default'',
    -> balance decimal(10,2) not null default 0.0
    -> );
  • 开始一个事务start transaction;
  • 创建一个保存点savepoint 保存点名;
  • 回到保存点rollback to 保存点名;
mysql> start transaction; --开启事务
Query OK, 0 rows affected (0.00 sec)

mysql> savepoint aa;  --设置保存点aa
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account value(1,'zs',10);--插入一条记录
Query OK, 1 row affected (0.02 sec)

mysql> savepoint bb; --设置保存点bb
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account value(2,'ls',100000);--再插入一条记录
Query OK, 1 row affected (0.00 sec)

mysql> select * from account;--查看记录,两条都在
+----+------+-----------+
| id | name | balance   |
+----+------+-----------+
|  1 | zs   |     10.00 |
|  2 | ls   | 100000.00 |
+----+------+-----------+
2 rows in set (0.01 sec)

mysql> rollback to bb;--回滚到bb状态
Query OK, 0 rows affected (0.01 sec)

mysql> select * from account;--此时第2条记录没有了
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | zs   |   10.00 |
+----+------+---------+
1 row in set (0.00 sec)

mysql> rollback to aa;--回滚到aa状态
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;--此时第一条记录也没有了
Empty set (0.00 sec)

事务操作的注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚事务的开始。直接使用rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回滚(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB支持事务,MyISAM不支持事务
  • 开始事务使用start transaction

事务的隔离级别

我们怎么解决隔离性的问题呢?那就是上锁,其实和JAVA的线程是一样的,多个线程调用同一个资源的时候,一但某一个线程调用到该资源,那么别的线程就不能在调用这个资源,也是加锁。
MySQL提供了一种机制,可以让不同的事务在操作数据时,具有隔离性。从而保证数据的一致性。
在这里插入图片描述

无隔离性的问题

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

举个例子:A的原工资为1000,财务人员将A的工资改为8000(但未提交事务);A此时读取自己的工资,发现变为8000;而财务发现是自己操作有误,回滚了事务,将A的工资又变为1000。这种情况A的工资8000就是一个脏数据。

  • 不可重复读
    是指在一个事务内,多次读同一数据,在这个事务还没有结束时,另外一个事务也访问该数据。那么在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能就是不一样的。这样就发生了在一个事务中两次读到的数据是不一样的,因此成为不可重复读。(即不能读到相同的数据内容)

举个例子:在事务1中,A读取了自己的工资为1000,操作并没有完成;在事务2中,这时财务人员修改了A的工资为2000,并提交了事务;在事务1中,A再次读取自己的工资,此时工资变为2000。
解决方法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

  • 幻读
    是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一事务的用户发现表中还有没有修改的数据行,就好像发生了幻觉一样。
    举个例子:目前工资为1000的员工有10人;事务1,读取所有工资为1000的员工;此时事务2向employee表中插入了一条员工记录,工资也是1000;事务1再次都区所有工资为1000的员工,共有11条记录。
    解决方法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题

  • 设置事务的隔离级别
    语法:

set session transaction isolation level read uncommitted;

读未提交:read uncommitted
读已提交:read commited
可重复读:repeatable read
可串行化:serializable

  • 查看当前事务的隔离级别
    语法:select @@tx_isolation;
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+

MySQL默认的隔离级别是可重复读,一般情况下不要修改

事务的ACID特性

  • 原子性
    事务是应用中最小的执行单位,就像原子是自然界的最小颗粒一样,具有不可再分的特征一样,事务是在应用中不可在分的最小逻辑执行体
  • 一致性
    事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
  • 隔离性
    同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
  • 持久性
    持久性是指一个事务一旦被提交,它对数据库所做的改变都要记录到永久存储其中
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值