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`) )
INSERT INTO `bank` VALUES (0, 'zhangsan', 1000), (0, 'lisi', 2000), (0, 'wangwu', 500), (0, 'zhaoliu', 1300);
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)