65 事务的隔离级别 , 脏读 可重复读

1MYISAMI 表锁与INNOdb 行锁之间的区别

2, Spring 中事务声明与编程事务之间的区别

3,手动事务流程: being, commit/rollback

,4,事务只做beign,不 commit/rollback 会发生哪些情况;

5, 站在事务角度分析: MyISAM 与Innodb 引擎之间的区别

6,脏读/可重复读/不可重复读/幻读之间的区别

  1. 事务隔离级别 读未提交/读提交/可重复读/串行化之间的区别;

8 MVVC(多版本并发控制)架构设计原理;

锁的分类:
表锁与行锁
锁概念:
锁分类:悲观与乐观锁
锁类型:重入锁、公平锁与非公平 排他锁 读写锁 共享锁

悲观与乐观锁
悲观锁:在没有获取锁的线程可能会阻塞等待
运行→阻塞
用户空间切换内核空间

乐观锁:乐观 在没有获取锁的线程当前线程一直在运行状态
通过循环控制自旋不断重试获取锁。
优点:效率比较高 不需要用户空间切换内核空间
缺点:消耗cpu的线程资源。

表锁 :
概念:
多个session会话连接,对同一张表做写的操作的时候,最终只有
一个session能够对该张表做写的操作;

锁的粒度非常大,发生锁的冲突概率比较高,效率非常低,
不能支持高并发;

行锁:
概念:多个session会话连接,访问同一张同一行数据的时候,最终只有
一个session能够对该行做写的操作;更高支持高并发。
锁的粒度变小,只是对一行数据上锁

表锁:
对锁:
当前session和其他session都可以读该表
当前session中插入或者更新锁定的表都会报错,其他session插入或更新则会等待

MyISAM表锁实现原理

CREATE TABLE `mayikt_lock_myisam` (
    `id` INT (11) NOT NULL AUTO_INCREMENT,
    `NAME` VARCHAR (20) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE = MyISAM DEFAULT CHARSET = utf8;


INSERT INTO  mayikt_lock_myisam (`id`, `NAME`) VALUES ('1', 'mayikt');


INSERT INTO  `mayikt_lock_myisam` (`id`, `NAME`) VALUES ('2', 'xiaowei');
INSERT INTO   `mayikt_lock_myisam` (`id`, `NAME`) VALUES ('3', 'xiaoan');
INSERT INTO   `mayikt_lock_myisam` (`id`, `NAME`) VALUES ('4', 'xiaomin');

手动新增表锁:
lock table 表名称 read(write), 2 read(write)

查看表上加过的锁
show open tables
删除表锁
unlock tables
1, 对表加锁
例如:先执行lock table mayikt_lock_myisam read;
在执行INSERT INTO mayiktdb.mayikt_lock_myisam (id, NAME) VALUES ('6', 'Xiaomin');
报错:1100 - Table 'mayikt_lock_myisam' was not locked with LOCK TABLES
当前session和其他session都可以读该表
当前session中插入或者更新锁定的表都会报错,其他session插入或更新则会等待

select * from mayikt_lock_myisam;
2.对表加写锁
例如:先执行lock table mayikt_lock_myisam write;
当前session对该表的增删改查都没有问题,其他session对该表的所有操作被阻塞
Innodb 与MyISAM
1,Innodb 使用行锁 有可能存在死锁;
2,Innodb中存在事务
3,MyIASM 使用表锁
4,MyISAM 没有事务概念
5,MyISAM 不带条件统计count 比 Innodb 快

InnoDB行锁实现原理
1.每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。
2.InnoDB与MYISAM的最大不同有两点:
支持事务(TRANSACTION)
支持行级锁

行锁支持事务:

事务(Transaction)以及 ACID 属性
事务是由一组SQL 语句组成的逻辑处理单元,事务具有4个属性,通常称为ACID
原子性(Atomicity): 事务是一个原子操作单元,对其数据的修改要不全部执行,要不全部不执行。
一致性(Consistent): 在事务开始和完成时,数据都必须保持一致状态,这意味着所有相关的数据规则都必须对应的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B 树索引或双向链表)也都必须是正确的;
隔离性(Isolation): 数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立环境”运行,这就意味着事务处理过程中的中间状态对外部是不可见的,反之亦然;
持久性(Durable): 事务完成后,他对于数据的修改时永久性的,即使出现系统故障也能够保持;

Spring 的事务组成部分;
SPring 中的事务由声明事务和编程事务组成
声明事务 : 使用注解或者扫描包方式配置事务;
编程事务: 手动beign ,commit/rollback 操作;

事务的传播行为: 7种spring 体系:
事务的隔离级别: 4种 mysql体系
使用事务注意事项: try
事务原理基于 aop 代理模式实现;
事务只做begin,不commit/rollback会发生那些情况?

Value的值为ON,表示autocommit开启。OFF表示autocommit关闭
set autocommit=0;---关闭

1、用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交

select * from information_schema.innodb_trx t
select t.trx_mysql_thread_id from information_schema.innodb_trx t
kill 768; --清理未提交的事务

事务只做beign,不做 commit/roolback 会发生哪些情况
有可能会导致其他session 在操作这行数据的时候一直阻塞等待;
线程A

begin;
update mayikt_account set name='meite11' where id=1;
commit;
select * from mayikt_account;


线程B

begin;
update mayikt_account set name='meite11' where id=1;

MySql 事务隔离级别:
谈到事务隔离级别之前事务相关的名字:
脏读:
脏读是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定最终存在的数据,这就是脏读;
可重复读
可重复读指的是在一个事务内, 最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致性的。通常针对数据更新(UPDATE)操作

不可重复读:
对比可重复读,不可重复读指的是在同一事物内,不同的时刻读到的同一批数据可能是不一致的,可能会受到其他事务的影响。比如其他事务改了这批数据并提交了。通常针对数据更新(uodate) 操作;
幻读
幻读是针对数据插入(INSERT)操作来说的,假设事务A 对某些操作的内容做了修改,但是还没提交,此时事务B 插入了与A 事务更改前记录相同的记录行,并且在事务A 提交前先提交了,而这时,在事务A 中查询,会发现好像刚刚的更改对于某些数据未起作用,其实是事务B 刚插入进来的,让用户感觉魔幻,这就是幻读。

SQL 标准定义了四种隔离级别, MYSQL 全都支持,这四种隔离级别分别是
读未提交(READ UNCOMMITTED)
读提交 (READ COMMITTED)
可重复读 (REPEATABLE READ)
串行化 (SERIALIZABLE)

从上往下,隔离级别强度逐渐增强,性能逐渐变差,采用哪种隔离级别要根据系统需求权衡决定,其中,可重复读是MySQL 的默认级别;

事务隔离级别就是为了解决上面提到的脏读, 不可重复读,幻读几个问题,下面展示了4种隔离级别对这是三个问题的解决程度;

[图片上传失败...(image-b7866c-1603936625639)]

mysql默认的事务隔离级别为 repeatable-read 可重复读
select @@transaction_isolation;

image.png

MySQL8查询tx_isolation为空的问题解决
transaction_isolation在MySQL 5.7.20中添加了作为别名 tx_isolation,现已弃用,并在MySQL 8.0中删除。应调整应用程序transaction_isolation以优先使用 tx_isolation。

换成transaction_isolation,后就能正常查询mysql8当前的默认事物的隔离级别了

事务隔离级别案例分析
1.读未提交 可能会产生脏读
set transaction_isolation='read-uncommitted';

sessionA 执行

set transaction_isolation='read-uncommitted';
select @@transaction_isolation;
begin ;
select * from mayikt_account;
update mayikt_account  set balance=balance-50 where id=1;
commit;


如果我们的sessionA执行rollback;的情况下,sessionB使用脏读数据操作。
sessionB执行

set transaction_isolation='read-uncommitted';
select @@transaction_isolation;
use mayiktdb;
begin ;
select * from mayikt_account;


commit;

2.读已提交 避免脏读的问题
set transaction_isolation='read-committed';

sessionA


set transaction_isolation='read-committed';
select @@transaction_isolation;
begin ;
select * from mayikt_account;
update mayikt_account  set balance=balance-50 where id=1;
commit;

sessionB


set transaction_isolation='read-committed';
select @@transaction_isolation;
begin ;
select * from mayikt_account;
update mayikt_account  set balance=balance-50 where id=1;
commit;

3.可重复读
set transaction_isolation='repeatable-read';
sessionA

set transaction_isolation='repeatable-read';
select @@transaction_isolation;
begin ;
select * from mayikt_account;
update mayikt_account  set balance=balance-50 where id=1;
commit;

sessionB

set transaction_isolation='repeatable-read';
select @@transaction_isolation;
begin ;
select * from mayikt_account;
commit;

4, 串行化,
串行化是4种事务隔离级别中隔离效果最好的,解决了脏读,可重复读,幻读的问题,但是,效果也最差,他将事务的执行变为顺序执行,与其他三个隔离级别相比,他相当于单线程,后一个事务一定要等前一个事务结束。

sessionA

set transaction_isolation='serializable';
begin ;
update mayikt_account  set balance=balance-50 where id=1;
commit;

sessionB

begin ;
select * from mayikt_account where balance='500';
INSERT INTO `mayikt_account` VALUES (null, 'yushengjun888', '500');


你可能感兴趣的:(65 事务的隔离级别 , 脏读 可重复读)