一个事务其实就是一个完整的业务逻辑。
是一个最小的工作单元,不可再分。
什么是一个完整的业务逻辑?
假设进行转账,从A账户向B账户转账1000,
将A账户的余额减去1000(update 语句)
将B账户的余额加上1000(update 语句)
这就是一个完整的业务逻辑。
以上操作是一个最小的工作单元,要么同时成功,要么同时失败,不可再分。
以上两个DML语句才会有事务这一说,其它语句和事务无关。
insert
delete
update
只有以上三个DML语句和事务有关系,其它语句和事务都无关。
因为只有以上三个语句是对数据库表中数据进行增、删、改的。
一旦涉及数据的增、删、改操作,那么一定要考虑安全问题。
数据安全第一位。
假设所有的业务,只要一条DML语句就能完成,还有必要存在事务机制吗?
一件复杂的业务,往往需要多条DML语句联合完成,所以才需要事务机制的存在。
如果任何一件事都能一条DML语句完成,那么事务就没有存在的价值了。
说到底,一个事务就是多条DML语句同时成功,或者同时失败。
事务:批量的DML语句同时成功或同时失败。
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件。
事务开启了:
insert
insert
delete
update
update
事务结束了。
在事务的执行过程中,每一条DML的操作都会记录到“事务性活动的日志文件”中。
在事务的执行过程中,我们可以提交事务,也可以回滚事务。
提交事务:
回滚事务:
事务对应的英语单词是:transaction
每执行一条DML语句,就提交一次。
测试:
mysql> select * from t_vip; Empty set (0.00 sec) #插入记录 mysql> insert into t_vip(name) values('ZhangSan'); Query OK, 1 row affected (0.05 sec) mysql> insert into t_vip(name) values('ZhangSan'); Query OK, 1 row affected (0.01 sec) mysql> insert into t_vip(name) values('ZhangSan'); Query OK, 1 row affected (0.01 sec) #查看表中数据 mysql> select * from t_vip; +----+----------+ | id | name | +----+----------+ | 1 | ZhangSan | | 2 | ZhangSan | | 3 | ZhangSan | +----+----------+ 3 rows in set (0.00 sec) #回滚事务 mysql> rollback; Query OK, 0 rows affected (0.00 sec) #再次查看表中数据 mysql> select * from t_vip; #数据还在 +----+----------+ | id | name | +----+----------+ | 1 | ZhangSan | | 2 | ZhangSan | | 3 | ZhangSan | +----+----------+ 3 rows in set (0.00 sec)
这种自动提交机制实际上是不符合我们的开发习惯的。因为一个业务通常需要多条DML语句共同执行才能完成的,为了保证数据的安全,必须要求同时成功之后再提交,所以不能执行一条就提交一条。
执行命令:start transaction;
上面的命令意为开启事务,也标志着关闭了自动提交机制。
#清空表中数据 mysql> truncate table t_vip; Query OK, 0 rows affected (0.02 sec) #表已空 mysql> select * from t_vip; Empty set (0.00 sec) #开启事务,关闭自动提交 mysql> start transaction; Query OK, 0 rows affected (0.01 sec) #插入数据 mysql> insert into t_vip(name) values('LiSi'); Query OK, 1 row affected (0.01 sec) mysql> insert into t_vip(name) values('LiSi'); Query OK, 1 row affected (0.00 sec) mysql> insert into t_vip(name) values('LiSi'); Query OK, 1 row affected (0.00 sec) #查看表,已有数据 mysql> select * from t_vip; +----+------+ | id | name | +----+------+ | 1 | LiSi | | 2 | LiSi | | 3 | LiSi | +----+------+ 3 rows in set (0.00 sec) #回滚事务,事务结束 mysql> rollback; Query OK, 0 rows affected (0.05 sec) #再次查看表,数据没有了 mysql> select * from t_vip; Empty set (0.00 sec)
mysql> select * from t_vip; Empty set (0.00 sec) #开启事务,关闭自动提交 mysql> start transaction; Query OK, 0 rows affected (0.00 sec) #插入数据 mysql> insert into t_vip(name) values('WangWu'); Query OK, 1 row affected (0.05 sec) mysql> insert into t_vip(name) values('WangWu'); Query OK, 1 row affected (0.00 sec) mysql> insert into t_vip(name) values('WangWu'); Query OK, 1 row affected (0.00 sec) #提交事务,事务结束了 mysql> commit; Query OK, 0 rows affected (0.00 sec) #查看表,已有数据 mysql> select * from t_vip; +----+--------+ | id | name | +----+--------+ | 1 | WangWu | | 2 | WangWu | | 3 | WangWu | +----+--------+ 3 rows in set (0.00 sec) #回滚事务 mysql> rollback; Query OK, 0 rows affected (0.00 sec) #再次查看表,数据还在 mysql> select * from t_vip; +----+--------+ | id | name | +----+--------+ | 1 | WangWu | | 2 | WangWu | | 3 | WangWu | +----+--------+ 3 rows in set (0.00 sec)
事务具备四个特性:原子性、一致性、隔离性、持久性。简称ACID。
A教室和B教室之间有一道墙,这道墙可以很厚,也可以很薄。这就是事务的隔离级别。这道墙越厚,隔离级别就越高。
事务与事务之间的四个隔离级别:
查看当前数据库隔离级别:select @@tx_isolation;
mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ |#mysql默认的隔离级别 +-----------------+
被测试的表:t_vip
设置数据库隔离级别:
set global transaction isolation level 隔离级别;
设置隔离级别为:read uncommitted
set global transaction isolation level read uncommitted;
退出mysql,然后重新打开两个dos窗口,都进入mysql。
左边的窗口代表事务A,右边的窗口代表事务B。
分别在左右两个窗口使用tsccg数据库,并开启事务:
开始测试:
设置隔离级别为:read committed
set global transaction isolation level read committed;
退出mysql,然后重新打开两个dos窗口,都进入mysql。
左边的窗口代表事务A,右边的窗口代表事务B。
分别在左右两个窗口使用tsccg数据库,并开启事务:
开始测试:
设置隔离级别为:repeatable read
set global transaction isolation level repeatable read;
退出mysql,然后重新打开两个dos窗口,都进入mysql。
左边的窗口代表事务A,右边的窗口代表事务B。
分别在左右两个窗口使用tsccg数据库,并开启事务:
开始测试:
设置隔离级别为:serializable
set global transaction isolation level serializable;
退出mysql,然后重新打开两个dos窗口,都进入mysql。
左边的窗口代表事务A,右边的窗口代表事务B。
分别在左右两个窗口使用tsccg数据库,并开启事务:
开始测试: