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

萨瓦迪卡5个月前 (08-28)MySql837

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

二、事务的原理是什么?

事务的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()代码控制业务回滚)


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

分享给朋友:

相关文章

js限制input只能输入数字、英文、汉字

 1.只能输入数字和英文的:  <input onkeyup="value=value.replace(/[\W]/g,'') "...

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

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

   /**      195.     * 发送...

freemarker 判断日期变量为空处理 及InvalidReferenceException异常处理

at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:98);InvalidR...

MyEclipse 10 性能大优化

MyEclipse 10 性能大优化

 MyEclipse 10已发布,新版本的特性能够大大提高开发者的效率。但同时,由于电脑配置的原因,很多开发者在使用MyEclipse的时候,速度都不是很快,需要我们对MyEclipse进行...

js/jquery 日历控件及实例下载

js/jquery 日历控件及实例下载

实现日历控件效果:页面:<link href="${base}/resource/${profile.path}/css/lhgcalendar.css" rel="...

谈话让别人舒服的程度,决定你成功的高度

职场上,有这样两种截然相反的人:有人生怕别人舒服,尽量让别人不舒服,而只要自己舒服就行;还有一类人生怕别人不舒服,尽量让别人舒服,哪怕委屈自己。猎头公司猎聘的老总有几十万年薪的,也有几百万的,甚至有过...

评论列表

quickq官网
1周前 (01-07)

投楼主一票,不用谢哦!https://www.quickq9.com

QuickQ
5天前

看了这么多帖子,第一次看看到这么有内涵的!https://www.quickq9.com

发表评论

访客

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