MySQL 事务

目录

一、什么是事务

二、事务的特性

三、事务使用案例

四、事务并发问题

五、设置事务的隔离级别(解决读的问题)


一、什么是事务

        MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!在 MySQL 中,事务是一组SQL语句的执行,它们被视为一个单独的工作单元。

        简单来说,事务:组成各个数据的执行的单元,要么都成功,要么都不成功。

举例: 转账的功能,冠希给美美转1000元钱。开启使用事务,先给冠希扣除掉1000元,再给美美加上1000元,事务结束了。(防止冠希扣钱了,但是美美没有收到)

二、事务的特性

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

三、事务使用案例

MySQL 事务_第1张图片

MySQL 事务_第2张图片

四、事务并发问题

不考虑事务的隔离性会引发的问题(理解)

1.脏读:一个事务读取到了另一个事务未提交的数据!

脏读(Dirty Read)发生在一个事务读取了另一个事务未提交的数据。如果那个事务回滚,读取的数据就是无效的。例如,事务A读取了事务B修改但未提交的数据,如果事务B回滚,事务A读到的就是“脏”的数据。

MySQL 事务_第3张图片

2.不可重复读:一个事务读取到了另一个事务提交的数据,导致了多次查询的结果不一致。强调的是update,修改记录 的数据。

不可重复读(Non-Repeatable Read)是指在同一事务中,多次读取同一数据集合时,由于其他事务的修改提交,导致两次读取的数据不一致。例如,事务A读取了一条数据,事务B修改了这条数据并提交,当事务A再次读取时,数据已经发生变化。

3.虚度(幻读):一个事务读取到了另一个事务提交的数据,导致了多次查询的结果不一致。强调是insert,向表中添 加一条数据。

幻读(Phantom Read)指的是当一个事务重新执行一个查询时,返回一组符合查询条件的结果集,但这个结果集中包含了另一个事务新增的数据。例如,事务A根据条件查询得到N条数据,事务B插入了符合条件的新数据,当事务A再次执行查询时,就会发现多了数据。

五、设置事务的隔离级别(解决读的问题)

1.事务的隔离级别(设置数据库的隔离级别,根据级别的不同,解决上述的读的问题) * Read uncommitted‐‐ 什么都解决不了 * Read committed * Repeatable read * Serializable‐‐ 避免脏读,但是不可重复读和虚读有可能产生‐‐ 避免脏读和不可重复读,虚度有可能产生的‐‐ 避免各种读

2.4种隔离级别有安全性和效率

安全 Serializable > Repeatable read > Read committed > Read uncommitted * 

效率 Serializable < Repeatable read < Read committed < Read uncommitted

3.数据库都有自己默认的隔离级别 * MySQL的数据库,默认的隔离级别是Repeatable read,避免脏读和不可重复读。

演示脏读

1.脏读:一个事务读取到了另一个事物未提交的数据。

2.进行测试 * 开启两个窗口,一个A窗口(左),一个B窗口(右)。
* 在A窗口中,查询A窗口的隔离级别:select @@tx_isolation;
* 设置A窗口的隔离级别为最低级别: set session transaction isolation level read uncommitted; 避免脏读和演示不可重复读   避免不可重复读  

* 设置A窗口的隔离级别为最低级别: set session transaction isolation level read uncommitted;     * 在两个窗口中,都开启事物     * start transaction;        
* 在B窗口中完成转账的工作。(冠希给美美转1千钱)     * update t_account set money = money ‐ 1000 where username = '冠希';         * update t_account set money = money + 1000 where username = '美美';        
* 注意:B窗口的事物未提交。        
* 在A窗口中,查询的结果(美美)    * select * from t_account;        
* 在B窗口中,回滚的是事物     * rollback;

避免脏读和演示不可重复读       

1.避免脏读的发生,提高的隔离级别。* set session  transaction isolation level  read committed;          * 在两个窗口中,都开启事物     * start transaction;        
* 在B窗口中完成转账的工作。(冠希给美美转1千钱)     * update t_account set money = money ‐ 1000 where username = '冠希';         * update t_account set money = money + 1000 where username = '美美';        
* 注意:事物还是没有提交,但是你需要观察A窗口中是否能读取到B创建未提交的数据。         * 在A窗口中,查询的结果(美美)     * select * from t_account;                 
* 在B窗口中把事物提交了     * commit;             
* 在A窗口中,再查询一次钱。    
* 两次查询的结果不一致,发生了不可重复读。

避免各种读

1.设置隔离级别:set session transaction isolation level serializable;
* 在两个窗口中,都开启事物 * start transaction;
* 在B窗口中添加一条数据 * insert into t_account values (null,'小苍',10000);
* 注意:没有提交事物
* 在A窗口中查询数据库 * select * from t_account;

你可能感兴趣的:(mysql,数据库)