一、事务
1、指的的逻辑上的一组(一组sql,insert update ,delete)操作,组成这组操作的各个单元(各个sql),要么全部成功,要么全部失败。
2、开启事务:开启一个事务。以后的sql都在一个事务中。更改的内容不会自动提交。
start transaction;
3、修改:对事务进行修改:
UPDATE account set money=money+100 WHERE name='小红';
4、保存点:
savepoint 保存点名; 设置保存点
rollback to 保存点名 : 回滚到某个保存点
5、回滚:事务的回滚—同时失败的情况。--事务结束,并且全部失败,数据回复到开始之前的状态
rollback;
6、提交事务:事务的提交----同时成功---事务结束。全部成功。
commit;
7、注意:
7.1、事务只对数据有变化的时候有效
7.2、数据在增删改的时候有变化
7.3、查询数据对数据本身没有影像
7.4、事务管理只对DML有效,被事务管理SQL语句可以回滚到SQL执行前状态
7.5、要做某件事,需要插入、修改、删除3条记录
每次执行一次,就在缓存中存一下
在缓存中存过3次,才能把这个事情干完
成功--commit--修改--一系列的结果,并清除以上几步的缓存
失败(异常或者数据修改出错)--rollback--修改不成功,回到最初的状态,当做没有发生,并清除以上几步的缓存
二、事务的特性ACID:
1、原子性(Atomicity):原子性是指事务是一个不可分割的工作单位(最小的一个整体),事务中的操作要么都发生,要么都不发生。
一组操作是一个整体。不能分割。
2、一致性(Consistency):事务前后数据的完整性必须保持一致。一致性和原子性相关。只有都成功或者,都失败(原子性) ,就可以保证事务的一致性。
事务的前后一致:a可以给b转账,b也可以给a转账,但是他们的总额不能变
3、隔离性(Isolation):事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
多个事务是独立存在的。多个事物不能够相互干扰。
a –b---事务A
;c-d---事务B
;如果A失败了。不能够影响B
4、持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
rollback和异常都不会对数据再构成影响了;
5、事务的隔离级别:
5.1、如果不考虑事务的隔离性,将会产生一下问题:
由数据的并发造成的问题:
1)、脏读:(同时操作没有提交的读取)
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
2)、不可重复读:同时操作,事务一分别读取事务二操作时和提交后的数据,读取的记录内容不一致)
不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。 解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ
3)、幻读:(和不可重复读类似,但是事务二的数据操作仅仅是插入和删除,不是修改数据,读取的记录数量前后不一致)
例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入(注意时插入或者删除,不是修改))了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样。这就叫幻读。
4)、同一条记录 内容的改变 不可重复读--update
条目数的改变 幻读---insert delete
例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入(注意时插入或者删除,不是修改))了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样。这就叫幻读。
5.2、数据库的事务隔离级别(四种)
set session\global transaction isolation level 设置事务隔离级别
select @@tx_isolation 查询当前事务隔离级别
1)、Serializable:可避免脏读、不可重复读、幻读情况的发生。(效率低)(串行化,一个事务一个事务运行)
set session transaction isolation level serializable;
注意:
A窗口在B窗口未提交数据的时候一直等待B窗口提交事务;等待时间过长会出现超时情况
A窗口不会出现脏读、不可重复读、幻读等情况,因为A窗口获取的是最新的数据。让操作数据的对象排队执行,会减低效率,一般数据库也不用。
2)、Repeatable read:可避免脏读、不可重复读情况的发生。 (可重复读)【不可以避免幻读】
set session transaction isolation level repeatable read;
注意:
A窗口在B窗口未提交数据的时候无论读取多少次,结果都是一样的,这样就解决了脏读;
A窗口在B窗口提交之前和提交之后第二次读到的数据一样的情况,解决了不可重复读。
A窗口在自己提交之前和自己提交之后读取到的数据条目不一致,可以理解为幻读;
3)、Read committed:可避免脏读情况发生。 (读已提交)【避免不了幻读以及不可重复读】
set session transaction isolation level Read committed;
注意:A窗口在B窗口未提交数据的时候无论读取多少次,结果都是一样的,这样就解决了脏读;
A窗口在B窗口提交之前读到的数据和B窗口数据提交之后第二次读到的数据不一样的情况,叫做不可重复读。
4)、Read uncommitted:最低级别,以上情况均无法保证。(读未提交)现实数据库没有使用这个隔离级别的
set session transaction isolation level read uncommitted;
注意:A窗口读取到了B窗口未提交的数据,如果B窗口回滚了,则A窗口读取出来的数据就是没用的,就是脏数据
5.3、注意:
1)、性能比较
Serializable 性能最差:事务一个一个执行的。排队。
Serializable < Repeatable read < Read committed < Read uncommitted
2)、安全性比较
Serializable 安全性最好:所有问题避免掉。
Serializable > Repeatable read > Read committed > Read uncommitted
3)、Read uncommitted 避免不了最重问题,脏读。
4)、Serializable:性能太差。
5)、mysql (默认)-- Repeatable read;(可重复读)
三、悲观锁、乐观锁
1、悲观锁:悲观锁是在数据库层加锁(for update)(当数据上锁(行锁或表锁)时,查询不受影响,增删改不允许被操作。)
1.1、操作时很悲观,生怕数据被其他人更新掉,我就先将其先锁住,让别人用不了,我操作完成后再释放掉。
1.2、加锁之前要先开启事务,
select * from test where id=3 for update; 对行加锁
select * from test for update; 对表加锁
2、乐观锁:乐观锁是在应用层加锁,
2.1、操作时很乐观,这数据只有我在用,我先尽管用,最后发现不行时就回滚。
3、注意:
3.1、一般来说如果并发量很高的话,建议使用悲观锁,否则的话就使用乐观锁。
3.2、如果并发量很高时使用乐观锁的话,会导致很多的并发事务回滚、操作失败。
3.3、总之,冲突几率大用悲观,小就用乐观。--数据安全性