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

萨瓦迪卡2个月前 (08-28)MySql236

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

二、事务的原理是什么?

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


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

分享给朋友:

相关文章

java将金额转化为大写金额

 private static String[] num = {"零","壹","贰","叁","肆...

揭秘!如何用一句话找到你的一万微友

 玩微商一年半的时间了,现在的微商如火如荼,很多刚进入微商行业的伙伴都在烦恼一个问题,那就是粉丝、粉丝,我最近调查了身边30多个微友,有25个竟然都是好友问题,有的竟然给我说主动加了50多个...

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

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

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

MyEclipse10.7注册码生成

注意经验里的工具可能不可用,请点击 生成注册码工具  下载。提取码:p1w4MyEclipse10.7注册码激活步骤:点击下面的链接http://jingyan.baidu.com/arti...

是谁动了我的座位

是谁动了我的座位

女孩一上火车,见自己的座位上坐着一男士。她核对自己的票,客气地说:“先生,您坐错位置了吧?” 男士拿出票嚷嚷着:“看清楚点,这是我的座,你瞎了?” 女孩仔细看了他的票,不再做声,默...

目标管理法——目标分解法

让自己的人生更幸福更有意义关键是:要将梦想转化为具体的目标,然后合理的分解,达到量化,指标化!现将学习到的两种非常有效的目标分解法分享给所有梦想、有激情的朋友:祝愿大家都能梦想成真! 一、俄...

评论列表

2K影视
16小时前

有机会找楼主好好聊聊!https://www.2kdy.com

发表评论

访客

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