是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)
事务的基本特性ACID
1.1. 原子性 (Atomicity)
事务开始后所有操作,要么全部做完,要么全部不做,不可能有半过程后再无其他操作。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
1.2. 一致性 (Consistency)
从宏观的角度来说,事务开始前和结束后,数据的完整性约束没有被破坏 。从微观的角度说,事务内的每一条子事务都按部就班完成。一致性着重取决于业务代码,
1.3. 隔离性 (Isolation)
同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。不同的隔离级别会有不同的效果。
1.4. 持久性 (Durability)
事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
* 先建立一个测试表user CREATE TABLE `user`( id INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(8), `balance` DECIMAL(10,2) ); * 插入测试数据 INSERT INTO `user` VALUES (1,'李明',5000),(2,'小李',80000); BEGIN; //开启事务(START TRANSACTION) UPDATe `user` SET balance = balance-2000 WHERe id=1; UPDATE `user` SET balance =balance+2000 WHERe id=2; COMMIT;//改变 BEGIN; UPDATE `user` SET balance = balance-2000 WHERe id=1; UPDATE `user` SET balance =balance+2000 WHERe id=2; ROLLBACK;//回滚 未改变事务隔离等级
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也很大。
| 事务隔离级别 | 脏读 | 不可重复读的 | 幻读 |
|---|---|---|---|
| 未提交读 | Y | Y | Y |
| 已提交读 | N | Y | Y |
| 可重复读 | N | N | Y |
| 串行化 | N | N | N |
隔离级别越高,性能越差
mysql默认的隔离级别是 repeatable-read
未提交读 (read-uncommitted)
最低的事务隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)。该级别用的很少。
已提交读 (read-committed)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变,换句话说就是事务提交之前对其余事务不可见,但是会导致不可重复读的问题。
可重复读 (repeatable-read)
是mysql默认使用的事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。
串行化 (serializable)
它强制事务都是串行执行的,使之不可能相互冲突,从而解决幻读问题。换言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
并发的事务问题1.脏读
读取到的是并未完成commit的数据,很不安全
例子:id=1的有3000余额,向2号id的人转账,转完之后并没有进行提交
这时2号查询自己账户发现3000已经转过来了
此时1号在输入rollback回滚,账户钱则回到了自己的账户
事务B能够读取事务A更新但未提交的数据,然后A回滚操作,那么B读取到的数据是脏数据。
首先,先把mysql默认事务开启关闭
SELECT @@autocommit;//显示为1为自动提交
默认事务开启:当我们执行一句sql时,效果就会立即体现出来,且不能回滚
默认事务关闭
SET autocommit=0;
查询mysql隔离级别
SELECT @@global.transaction_isolation; //系统级别 SELECT @@session.transaction_isolation; //会话级别
SESSION ,GLOBAL用来指定修改隔离级别的范围
SESSION表示修改的事务隔离级别应用于当前Session(当前cmd下)中的所有事务
GLOBAL表示修改的事务隔离级别应用于所有Session(全局)中的所有事务,且当前已存在的session不受影响
修改mysql隔离级别为未提交读
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
#1号操作...(事务A) BEGIN; SELECT * FROM `user` WHERe id=1; UPDATe `user` SET balance=balance-3000; UPDATE `user` SET balance=balance+3000;
#2号操作..(事务B) BEGIN; SELECT * FROM `user` WHERe id=2; commit;
#1号操作.... ROLLBACK;
2.不可重复读
修改mysql隔离级别为读已提交
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
#1号操作 查找账户余额 BEGIN; SELECt * FROM `user` WHERe id=1;
#2号此时操作 将1号账户余额转出2000 BEGIN; UPDATe `user` SET balance = balance+2000 WHERe id=2; UPDATE `user` SET balance = balance-2000 WHERe id=1; COMMIT;
#此时1号再次查账户,发现余额被取走了 SELECT * FROM `user` WHERe id=1; COMMIT;
已提交读隔离级别解决了脏读的问题,但是出现了不可重复读的问题,即事务A在两次查询的数据不一致,因为在两次查询之间事务B更新了一条数据。已提交读只允许读取已提交的记录,但不要求可重复读。
3.幻读
4.串行化
serializable完全锁定字段,若一个事务来查询同一份数据就必须等待,直到前一个事务完成并解除锁定为止。是完整的隔离级别,会锁定对应的数据表格,因而会有效率的问题。
排队,依次进行。
------------------------博客只是对个人学习做一个笔记,如有技术或侵权问题感谢纠正。------------------------
部分摘自链接:https://blog.csdn.net/qq_33710903/article/details/109644177



