mysql--TCL 叁歲伎倆 2022-10-23 08:28 145阅读 0赞 TCL 事务(transaction) 1. 什么是事务? 是一个完整的业务逻辑,不可再分. 比如:银行账户转账,从A账户向B账户转账10000, 需要执行两条update语句. update t_act set balance = balance - 10000 where actno = 'act-001'; update t_act set balance = balance + 10000 where actno = 'act-002'; 以上两条语句不许同时成功或者同时失败,不允许出现一条成功一条失败. 要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的"事务机制". 和事务相关的语句只有DML(insert, delete, update)语句. 为什么?因为他们这三个语句都是和数据库表当中的数据相关的. 事务的存在是为了保证数据的完整性,安全性. 假设某业务能使用1条DML语句搞定,还需要事务机制吗? 不需要. 2. 事务的原理. 开启事务: (事务的开始) insert... update... delete...(以上的DML语句执行成功之后,把这些语句记录到数据库的操作历史当中,并不会向文件中修改表中的数据,不会真正的修改硬盘上的数据) 提交事务或回滚事务(事务的结束) 3. 事务的四大特性:ACID A:原子性 C:一致性:事务必须保证多条DML同时成功或失败 I:隔离性:事务A与事务B之间具有隔离 D:持久性:最终数据必须持久化到硬盘文件中,事务才算成功的结束. 4. 事务的隔离级别, 理论上级别有4个: 第一级别: 读未提交(read uncommitted) 对方还未提交的数据我们可以读到.我们当前的事务可以读取到对方未提交的数据. 读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据. 第二级别: 读已提交(read committed) 对方事务提交后的数据我方可以读取到. 这种隔离级别解决了脏读现象. 读已提交存在的问题是:不可重复读(事务提交前后,两次读取的数据不一致.即使在自己不改动的情况下,也无法保证数据不会发生改动) 第三级别: 可重复度(repeatable read) 这种隔离级别解决了:不可重复读的问题. 出现的问题:读取到的数据都是幻象. 第四级别: 序列化读/串行化读(serializable): 解决了所有问题,两个事务不能并发, 必须排队. 存在的问题:效率低,需要事务排队. Oralce默认的隔离级别是第二级别, Mysql默认的隔离级别是可重复度. 5. 演示事务. Mysql事务默认情况下是自动提交的.(什么是自动提交?只要执行任意一条DML语句则提交一次.) 准备表: mysql> drop table if exists t_user; Query OK, 0 rows affected, 1 warning (0.04 sec) mysql> create table t_user ( -> id int primary key auto_increment, -> username varchar(255) -> ); Query OK, 0 rows affected (0.05 sec) mysql> rollback; Query OK, 0 rows affected (0.05 sec) mysql> select * from t_uset; ERROR 1146 (42S02): Table 'bjpowernode.t_uset' doesn't exist mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | +----+----------+ 怎么关闭自动提交事务? start transaction; 演示:使用start transaction关闭自动提交事务. mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> insert into t_user(id, username) values(2, 'lisi'); Query OK, 1 row affected (0.05 sec) mysql> insert into t_user(id, username) values(3, 'wangwu'); Query OK, 1 row affected (0.05 sec) mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.05 sec) mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | +----+----------+ 1 row in set (0.00 sec) 注意:每次都要使用事务的时候都需要输入一次 start transaction mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> insert into t_user(id, username) values(2, 'lisi'); Query OK, 1 row affected (0.05 sec) mysql> insert into t_user(id, username) values(3, 'wangwu'); Query OK, 1 row affected (0.05 sec) mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.00 sec) mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.00 sec) 6. 演示读未提交 在窗口2上操作: //这条语句的意思是"设置全局事务隔离等级为读未提交. mysql> set global transaction isolation level read uncommitted; Query OK, 0 rows affected (0.05 sec) 如何查看隔离级别? mysql> select @@global.transaction_isolation; +--------------------------------+ | @@global.transaction_isolation | +--------------------------------+ | READ-UNCOMMITTED | +--------------------------------+ 设置完成之后,两个窗口都推出mysql,再重新进入. 然后两张表都关闭自动提交事务. 窗口1, 查看t_user表. mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.05 sec) 窗口2, 向t_user插入一条数据.(事务还没提交) 窗口1, 再次查看t_user表 mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | | 4 | smith | +----+----------+ 4 rows in set (0.05 sec) 7. 读已提交 完成准备操作: 设置隔离等级,重启,关闭自动提交事务 窗口1: 查看表t_user; mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.04 sec) 窗口2: mysql> insert into t_user values(4, 'smith'); Query OK, 1 row affected (0.05 sec) (表未提交) 窗口1: 查看表t_user; mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | +----+----------+ 3 rows in set (0.04 sec) 窗口2: mysql> commit; //提交事务 Query OK, 0 rows affected (0.05 sec) 窗口1: 查看表t_user; mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | | 4 | smith | +----+----------+ 4 rows in set (0.00 sec) 8. 演示可重复读 一直在读本分数据(我猜存在内存当中) 窗口1: mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | | 4 | smith | +----+----------+ 4 rows in set (0.00 sec) 窗口2: mysql> delete from t_user; Query OK, 4 rows affected (0.05 sec) mysql> commit; Query OK, 0 rows affected (0.05 sec) mysql> select * from t_user; Empty set (0.00 sec) 窗口1: mysql> select * from t_user; +----+----------+ | id | username | +----+----------+ | 1 | zs | | 2 | lisi | | 3 | wangwu | | 4 | smith | +----+----------+ 4 rows in set (0.00 sec) //提交事务之后,再在窗口1查询该表. mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from t_user; Empty set (0.00 sec) 9. 序列化读
还没有评论,来说两句吧...