mysql transaction 事务

 

1、事务简介

  • 一个"最小的"不可再分的"工作单元"。
  • 一个事务通常对应了一个完整的业务。如:银行的转账功能,a转账给b,a扣钱,b加钱。
  • 一个事务包含一条或多条DML语句(insert,update,delete)。
  • 在一个事务中要么所有的语句都成功执行,要么都失败,即所有的DML语句都成功执行才会修改硬盘数据。

在mysql命令行模式下,事务是自动提交的,每执行一条DML语句都会开启一个事务,执行成功后立即执行commit操作。可以通过"show variables like '%commit%';"  查看事务的是否自动开启。

 

2、事务的四个属性

① 原子性:最小的工作单元,不可再分。事务中的所有操作必须全部成功或全部失败,成功后写入底层数据,失败后回滚rollback到事务开启的状态。

② 一致性:事务在完成时,必须使所有的数据都保持一致状态,保持数据库的完整性。

③ 隔离性:并发事务之间存在隔离,互不干扰。

④ 持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

 

3、事务控制语句

  • commit     事务提交
  • rollback    事务回滚
  • begin        开启事务
  • start transaction  开启事务 同begin
  • set transaction     设置事务隔离级别,只对当前会话有效

1)事务结束标志

  事务提交或回滚,在mysql中默认开启自动提交事务,即执行一条insert,update,,delect,会自动提交事务

2)关闭自动提交事务的方式1

  手动开启一个事务

begin;
    DML语句..
    DML语句..
    ...
commit/rollback;

3)关闭自动提交事务的方式2 ,这种方式最对当前会话有效。更改后通过 "show variables like '%commit%';" 查看事务开启状态

set autocommit = off;   # 关闭自动提交事务
set autocommit = on;   # 开启自动提交事务

 

4、事务四个隔离级别

  • read uncommitted  读未提交
  • read committed      读以提交
  • repeatable  read    可重复读
  • serializable            串行化

这四个隔离级别逐渐增高。

① read uncommitted:事务A未提交的数据,事务B也可以读取到,这种隔离级别最低。这种事务会导致"dirty read(脏读)"。因为事务A的数据还没有提交,事务B就可以读取到,那如果事务A在事务B读取后回滚了呢,就导致了事务B读取到的数据是"脏数据"。

② read committed:事务A未提交的数据,事务B读取不到,事务A提交后的数据事务B才能读取到。这个事务级别不会导致"dirty read",但会导致"不可重复读"。假设事务A需要半天,在这期间有很多的其它事务都在修改数据,那么就导致了一个问题,事务A在开启时读到的数据与半天后读到的数据差别很大,那么事务A需要在这半天内读到的数据都是一样的该怎么办,比如每个月底网络运营商系统出账的时候,那肯定得在出账期间读到的数据都必须一样才行。

③ repeatable  read:事务A提交后的数据,事务B读取不到,事务B读取的数据依旧是事务B刚开始时的数据。MySQL的事务默认是这个级别。

④ serializable:事务A在执行的时候,事务B只能等待,就是说当多个事务需要执行时,只能排队一个个的来,就是串行化的字面意思了。这种隔离级别最高,但会导致数据库的吞吐量很低一般不用。

 

5、实例

1)需要用到的表

CREATE TABLE `bank` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  `money` int(255) NOT NULL,
  PRIMARY KEY (`id`)
)
bank表
INSERT INTO `bank` VALUES (0, 'zhangsan', 1000), (0, 'lisi', 2000), (0, 'wangwu', 500), (0, 'zhaoliu', 1300);
bank表数据

2)'lisi' 给 'zhangsan' 转账 500

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update bank set money=money+500 where name='zhangsan';
Query OK, 1 row affected (0.01 sec)

mysql> update bank set money=money-500 where name='lisi';
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from bank;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | zhangsan |  1500 |
|  2 | lisi     |  1500 |
|  3 | wangwu   |   500 |
|  4 | zhaoliu  |  1300 |
+----+----------+-------+
4 rows in set (0.00 sec)
View Code

 

 

posted @ 2018-10-22 10:09  nonzero  阅读(6113)  评论(0编辑  收藏  举报