事务的概念
事务 : 指逻辑上的一组操,组成这组操作的各个单元,要么全部成功,要么全部失败.在不同的环境中,都可以有事务.对应在数据库,就是数据库事务.
事务的使用
(1)开启事务:start transaction;
(2)执行多条SQL语句
(3)回滚或提交:rollback/commit;
事务经典应用场景
比如转账The concept of transaction
账户1 ID 107 余额 10000;
账户2 ID 108 余额 0;
假设 1 给 2 转账 5000;
(1)update account1 set balance = balance - 5000 where ID = 107;
(2)update account2 set balance = balance + 5000 where ID = 108;
假如转账过程中执行完操作(1)
主机发生故障或者数据库崩溃了
此时账户2的钱未到账
事务的存在就是为了解决上述问题:
本质就是将多个sql语句打包成一个整体,要么全部执行要么一个都不执行(不是真的未执行而是执行一半出现错误后,选择恢复现场,将数据还原到先前的状态 --- 这个恢复数据的操作叫做回滚(rollback));而不会出现执行一半的情况
因为使用了事务,执行sql的开销更大,效率更低;
进行回滚的时候如何知道恢复到什么状态?
此时需要额外的部分记录事务的操作步骤(数据库里有专门记录事务的日志)
事务的四个关键特性
1.原子性(核心特性)
2.一致性(事务执行前后数据是靠谱的)
3.持久性(事务修改后的内容是写到硬盘上的,持续存在的)
4.隔离性(解决并发执行事务引起的问题(修改同一个表的同一数据))
隔离性存在的意义: 就是为了保证数据库在并发处理事务的时候减少问题的出现
并发执行事务可能产生的问题
1.脏读问题
事务A 在对数据进行修改时,事务B 对同一个数据进行读取,(后面可能还会修改)此时事务B 的操作叫做"脏读",读取的数据称为"脏数据";
解决办法:
为了解决脏读问题 Mysql 引入了"写操作加锁"这样的机制(事务A写的时候事务B不能读取,写完才能读取)
写加锁操作:降低了并发程度(降低效率)提高了隔离性(提高数据的准确性)
2.不可重复读
事务A已经提交了一次数据 ,此时事务B开始读数据,在读数据的过程中,事务C又提交了新的数据,此时意味着同一个事务B之内,多次读取数据数据,结果是不同的
(预期一个事务,多次读取的数据是一样的,就叫做不可重复读)
解决方法:
通过"读加锁"(约定事务B开始读的时候,不能修改)
3.幻读
已经约定"读加锁"和"写加锁" 解决了不可重复读和脏读问题
举例说明
假设某一天我(事务A)在敲代码,我的室友(事务B)在后面看,由于"读加锁",室友看的时候,我不能改代码了 --- 干坐着不是办法,那我就再创建一个代码(student.java)写,他看上一个代码(hello.java) 某些情况下,室友再读读到了student.java,表示不能理解;
在读加锁和写加锁前提下,一个事务读取两次数据,数据的值是一样的,当时发现结果集不同,这种叫做"幻读";
解决办法:
数据库使用"串行化"的方法解决幻读问题,彻底放弃并发处理事务,而是一个接着一个串行处理事务;这样操作的并发程度是最低的(效率慢),但隔离性是最高的(准确性也最高)
对于上述情况Mysal 提供了四种隔离级别