深入理解Mysql事务隔离级别与锁机制

一事务定义:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性。

二、事务的原理是什么?

事务的ACID特性:
  • 原子性(Atommicity):当前事务的操作要么同时成功,要么同时失败。原子性由undo log日志来实现。(比如,下单时候,会1生成订单、2减库存。入过库存不足,那么就回滚生成得订单。生成订单时undo log 会记录insert语句,和delete id=1语句,当减库存失败时,执行delete语句

  • 一致性(Consistency):使用事务的最终目的,由其它3个特性以及业务代码正确逻辑来实现。(比如,减库存时,try {减库存 }catch(打印日志)没有抛异常,也不会回滚。

  • 隔离性(lsolation):在多个事务并发执行时,他们内部的操作不能互相干扰,隔离性由MySQL的各种锁以及MVCC机制来实现。

  • 持久性(Durability):一旦提交了事务,它对数据库的改变就应该是永久性的.。持久性由redo log日志来实现

事务的隔离级别:innoDB 引擎中,定义了四种隔离级别。级别越高事务隔离性越好。隔离性是由Mysq的各种以及MVCC机制来实现的。
1read uncommit(读未提交)脏读(update语句后,没有执行commit,也能读到新数据,一旦rellback,就会撤销update。造成脏读事务A读取到了事务B已经修改但尚未提交的数据)
比如:set tx_isolation='read-uncommitted';
            begin;
            update account set balance = balannce +500 where id =1;
            ROLLBACK;
            commit;
2read commit(读已提交)oracle默认,不可重复读事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性
3repeatable read(可重复读)Mysql默认用这个级别,幻读事务A在修改语句后读到了事务B提交的新增数据。比如事务A第一次查是3条记录,库里加了第4条记录,然后事务A修改了id=4的记录后,再查是4条记录了).select查询的是快照(当时查询时库里的数据,历史版本),update修改的是最新数据。修改之后再查是查修改后的数据,其他没有修改的数据还是读之前快照里的数据。修改语句在事务里有行锁(属于悲观锁),未提交前,其他事务不可修改。
4serializable(串行):解决上面的所有问题,包括脏写。有个事务在查询着,其他事务就不能修改。不过性能较低,一般不用。它的实现原理就是:在所有的select语句后面加了一把读锁
常看当前数据库的事务隔离级别: show variables like 'tx_isolation';

设置事务隔离级别语句:set tx_isolation='read-uncommitted';

以上是基于Mysql5.7的,Mysql 8的语句 为:
常看当前数据库的事务隔离级别: show variables like 'isolation';
设置事务隔离级别语句:set transation_isolation='repeatable-read';


注意:在sql里面更新数据,就不会出现脏写的情况。不要在java里计算。

乐观锁,在表里加字段version,每次修改就+1.

  比如:set tx_isolation='read-committed';
    begin;
    select id,version,balance from account where id = 1;(1,1)
    java:1000+5=1500
    update account set balance =1500 where id =1 and version = 1;
    commit;
在前面加while,如果版本不存在,就再执行一次。直至成功。
可以在读未提交、读已提交中使用。

锁的分类:

   从性能上分为乐观锁(用版本对比来实现)和悲观锁
  从对数据库操作的类型分,分为读锁和写锁(都属于悲观锁)
  读锁(共享锁,S锁(Shared)):select ...lock in share mode
读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改。
  写锁(排它锁,X锁(eXclusive)):select... for update;
是排他的,当前写操作没有完成前,它会阻断其他写锁和读锁,update、delete、insert都会加写锁。
从对数据操作的粒度分,分为表锁和行锁。
面试题:查询操作方法需要使用事务吗?
·1如果有一条查询sql,不需要用事务
 2如果有多条查询,就要看情况。如果是可重复读的隔离级别,最好加一个事务。因为如果出报表的话,两个查询的值一定是同一时间维度的报表,当然可能不是最新数据,那就再查一遍就行了。如果是其他的读已提交的就不必用事务,因为加不加事务效果一样的情况下,不加事务性能更高。

事务的优化:

大事务的影响:
1并发情况下,连接池容易被撑爆
2锁定太多的数据,会造成大量的阻塞和锁超时
3执行时间长,会造成主从延迟
4回滚需要的时间比较长
5undo log会膨胀
6容易导致死锁
事务优化实践原则:
1将查询等数据准备操作放到事务外(如果是RC读已提交 级别可以,RR可重复读 不行)
2事务中避免远程调用,远程调用要设置超时。
3事务中避免一次性处理太多数据,可以拆分多个事务分次处理。
4更新等涉及加锁的操作尽可能放在事务靠后的位置(update 放事务后面,避免其他的事务等待)
5能异步处理的尽量异步处理
6应用层(业务代码)保证数据一致性,非事务执行(在代码里写tay{1,2,3}catch()代码控制业务回滚)


本文原创,转载必追究版权。

分享给朋友:

相关文章

get方式调用http接口   Header赋参数值

get方式调用http接口 Header赋参数值

   /**      195.     * 发送...

坑爹的ShowModalDialog 后台传值解决方案

 今天遇到需要ShowModalDialog打开页面,通过acceptanceIds 参数值后台过滤出相应结果前台  var url = "loadAccept...

Java 实现用户资料完整度的前端显示(或根据填写资料自动评分)

前端使用 Bootstrap 的进度条组件显示百分比,后台读取权重并计算信息完整度,并将计算的结果返回给前端,供页面显示。CSS1<link href="static/sc/...

我差不多是个废人了,感觉身体被掏空

林心如跟霍建华都结婚了,滴滴跟优步都在一起了。我们也应该抱住了吧? 终于8月了,超吃点吧,再一咬牙,坚持一下吧,马上秋天到了,就可以又能马上把肥肉藏起来了。 在这里迫不及待教大家一个夏天过后...

樊山越玲 一周年

樊山越玲 一周年

2015-12-25樊先森:周末有约吗?玲玲:有约,不过也得先以你为主啊。樊先森:昂,这样说我还挺开心的。2015-3-26玲玲:亲爱的,苹果是你买的吗?已经收到了,谢谢老公玲玲:有点小惊喜樊先森:那...

java 实现自增编号+Oracle序列

原理:a,a++,fillStr(a, 9, false, "0");新建序列:create sequence seq_lineminvalue 1maxvalue 9999999...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。