事务+事务隔离级别+事务特性+悲观乐观锁

事务

1、事务的概念:

事务是用来维护数据库完整性的,能够保证一系列的mysql操作要么全部执行,要么全部不执行
一个mysql语句就是一个事务
事务指的是一个操作序列,这个操作序列的多个操作要么全部执行,要么全部不执行,是不可分割的单位,是数据库环境中逻辑工作单位

2、事务的特征:

原子性:对数据的修改要么全部执行成功,要么全部失败(实现事务的原子性,基于redo/undo机制)
一致性:事务执行的结果从一个一致性状态,到达另一个一致性状态(前后状态要一直)
隔离性:事务的执行相互独立,不受影响
永久性:事务一旦提交,对数据库的改变,就会永远储存

3、Redo/Undo机制:

他们是将所有的更新操作写在日志中
redo log是用来记录某模块被修改后的值,可以用来回复未写入data file的已成功事务更新的数据
undo log是用来记录某模块更新前的值,保证数据更新失败后可以回滚
事务的开始/回滚/提交
开始:事务开启后,在回滚或提交之前,都针对缓存的数据做操作,而不是针对真是的数据
回滚:从开始到回滚这一段时间对数据做的更改,都不会操作数据库真是的数据
提交:从开始到提交之间做的所有的操作,都将一次性全部执行到真实的数据中
例题:

创建账户表(字段id name balance)
create table account
(id int primary key auto_increment,
name varchar(10) not null,
balance double);
查看账户表 select * from account;
插入数据 insert account values (1,aa,300),(2,bb,100);
转账
update account set balance = balance+200 where id=2;
update account set balance = balance-200 where id=1;
开启事务 start transaction
手动回滚,刚刚执行的操作全部取消 rollback;
手动提交 commit;

4、事务的隔离级别

1、 读未提交
读取到没有提交的数据,会造成脏读
2、 读提交
解决脏读的问题,但是会造成对一个事务在不同时间点读取的时候,读到的数据可能不一样(会受到其他事务对数据修改提交后的影响),也就是允许不可重复读取,不允许脏读,读取的事务允许其他事务继续访问,但是未提交的写事务进制其他事务访问,可以通过“瞬间共享读锁”和“排他写锁”实现
3、 可重复读
解决了前面脏读和不可重复读的问题,但是会带来幻读(前一秒对数据进行更改,等下一次发现又变为更改前的样子)读取数据的事务进制写,写事务禁止其他任何事务,可以通过“共享读锁”和“排他写锁”实现
4、 序列化
提供严格的事务隔离,要求事务序列化执行,只能一个接一个执行,不可以并发执行
隔离级别越高,越可以保证事务的完整性和一致性,但是对并发性能的影响越大,对多数,我们避免脏读,就隔离级别设置为读提交,尽管会造成幻读和不可重复读,但我们可以使用悲观锁,乐观锁来控制

5、悲观锁,乐观锁

悲观锁:
指对数据被外界修改持保守的态度,因此,在整个数据的处理过程中,将数据处于锁定状态(比如我们先查询出一条数据,然后对其近一步修改,但会出现问题就是我们查询到修改之间被别人更改了,那么可以使用悲观锁的原理,查询出来的时候就可以进行锁定,直到修改完毕后解锁,使用悲观锁的时候,必须关闭mysql的自动提交属性set cutocommit=0;)
select…for update的方式,这样就通过数据库实现了悲观锁
明确指定主键或者索引,mysql才会执行row lock(只锁住被选取的数据)否则将会执行table lock(锁住整个表单),查无此数据,谁都不锁
悲观锁小结:加锁过长,其他用户无法访问,会影响事务的并发访问,对性能开销影响大,于是有了乐观锁

乐观锁:
乐观锁假设认为数据一般情况下不会造成冲突,只有在提交更新的时候,才会对数据的冲突进行检测,如果发生冲突了,则会返回用户错误的信息,让用户决定如何去做
实现乐观锁的两种方式:
1、 版本号(为护具增加一个版本标识,数据每更新一次,对version值+1,提交更新的时候,当前和第一次去除的值比对,如果相等,就更新,否则认为过期),其实就是在更新的时候判断其他线程是否修改了数据,如果修改了就会拒绝更新
2、 时间戳,需要乐观锁 控制的table中增加一个字段,类型是时间吹,更新提交的时候检测与更新前是否一致,否则就是冲突
为什么不直接用事务隔离级别?
如果直接设置事务的隔离级别,就不饿能动态调整事务的隔离级别,性能上不好

6、设置事务的隔离级别

SET TRANSACTION ISOLATION LEVEL语句。
• 其语法模式为:
————————————————
set session transaction isolation level read uncommitted;
查看当前隔离级别:

select @@tx_isolation;
  		其中的<isolation-level>可以是:
  	–	READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE
  	•	例如: SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

**Tip1:**大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。
Mysql的默认隔离级别是Repeatable read。
**Tip2:**隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。
**Tip3:**设置数据库的隔离级别一定要是在开启事务之前。

猜你喜欢

转载自blog.csdn.net/weixin_44697051/article/details/119705911