mysql中的事务与锁

1、事务的四大特性

原子性,隔离性,持久性,一致性

原子性(Atomicity): 语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log

一致性(Consistency): 事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障

隔离性(Isolation): 保证事务执行尽可能不受其他事务影响;InnoDB默认的隔离级别是RR(可重复读 repeatable read),RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)

持久性(Durability): 保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log和双写缓冲

2、事务并发引起的三大问题(同一个事务两次读取的结果不一致)

脏读:一个事务读取到了其他事务未提交的数据,导致两次读取结果不一致

不可重复读:一个事务读取到了其他事务已提交的数据(update和delete),导致两次读取结果不一致

幻读:一个事务读取到了其他事务插入的数据,导致两次读取结果不一致

3、事务的隔离级别

读未提交(RU),事物A和事物B,事物A未提交的数据,事物B可以读取到,容易出现脏读

读已提交(RC),事物A和事物B,事物A提交的数据,事物B才能读取到,解决了脏读问题,一个事务读取了其他事务已提交的数据会出现不可重复读问题(oracle默认的隔离级别)

可重复读(RR),事务A和事务B,事务A提交之后的数据,事务B读取不到 - 事务B是可重复读取据,解决了不可重复读的问题,

串行化(serializable),事务A和事务B,事务A在操作数据库时,事务B只能排队等待,解决一切问题

4、Innodb是支持事务的,默认的隔离级别是RR(不需要用串行化就能解决所有问题,提高了并发性)

5、Innodb是运用了MVCC的核心思想

我可以查到在我这个事务开始之前已经存在的数据,即使它在后面被修改或者删 除了。在我这个事务之后新增的数据,我是查不到的

(1)一个事务能看到数据库的版本

第一次查询之前的版本

本事务修改的版本

(2)一个事务不能看见的数据库版本

在本事务第一次查询之后创建的事务(事务id大于本事务)

活跃的(未提交)的事务的修改

MVCC的效果是建立一个快照,同一个事务无论查询多少次都是相同的结果

MVCC的实现原理:

DB_TRX_ID,插入或更新行的最后一个事务的事务ID,事务编号是自动 递增的(创建版本)。
DB_ROLL_PTR,回滚指针(删除版本)。

MVCC的查找规则:只能创建版本小于当前版本事务的数据,能查到删除版本大于当前事务的数据

5、Read view(可见性视图)

每个事务都维护一个自己的read view ,其中包括当前系统最大的事务id,活跃的事务id,本次事务的id

1、从数据的最早版本开始判断(undo log) 1、数据版本的trx_id = creator_trx_id,本事务修改,可以访问 
2、数据版本的trx_id < min_trx_id(未提交事务的最小ID),说明这个版本 在生成ReadView已经提交,可以访问
3、数据版本的trx_id > max_trx_id(下一个事务ID),这个版本是生成 ReadView之后才开启的事务建立的,不能访问 
4、数据版本的trx_id 在min_trx_id和max_trx_id之间,看看是否在m_ids中。 如果在,不可以。如果不在,可以。
5、如果当前版本不可见,就找undo log链中的下一个版本。

5.1RC与RR Read View的区别

RR中Read View是事务第一次查询的时候建立的。 RC的Read View是事务每次查询的时候建立的。

6、mysql中innodb锁的基本类型,myisam只支持表锁

共享锁(S锁,读锁),排它锁(X锁,写锁),意向共享锁(表锁),意向排他锁(表锁)

共享锁可以重复获取,多读事务可以共享一把锁

排他锁是一个事务获取这行数据的排他锁,其他事务就不能对这行数据加共享锁和排他锁,

意向锁共享锁是在一个事务对一行数据加了共享锁,就会在这个表上加一个意向共享锁,意向排它锁也是如此,意向锁是为了提高锁的效率的,意向锁是数据库自己维护的,

当需要向一张表加表锁的时候,如果没有意向锁需要判断是否有行锁,加了意向锁,就可以直接判断表里面是否加了行锁

innodb的行锁是通过锁住索引来实现的

根据锁的算法又分为记录锁和间隙锁

当查询的数据命中的时候是用记录锁

当查询的数据没有命中或者是一段范围的使用的是间隙锁

临键锁是间隙锁加记录锁

7 查看锁信息

show status like 'innodb_row_lock%'    -- 查看行锁
-- Innodb_row_lock_current_waits正在等待锁的数量
-- Innodb_row_lock_time从系统启动到现在锁定的总时间长度,单位是ms
-- Innodb_row_lock_time_avg 每次平均等待说话的时间
-- Innodb_row_lock_time_max从系统启动到现在等待最长的一次所花的时间
-- Innodb_row_lock_waits 从系统启动到现在总共等待的次数


select * from information_schema.INNODB_TRX -- 当前所有运行的事务和语句
select * from information_schema.INNODB_LOCKS -- 当前出现的锁
select * from information_schema.INNODB_LOCK_WAITS -- 锁等待的对应关系

如果有事务长时间持有锁不释放,可以先kill掉这个事务对应的线程id,就是INNODB_TRX中对应的trx_mysql_thread_id

8 死锁的避免

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值