ACID特性
原子性 atomicity 事务是一个原子 操作,要不全部执行,要么全部不执行
持久性 durability 事务一旦提交,对数据库中数据的改变是永久的,后续的操作或故障不应该对其产生影响(例如其他事物会滚,不会影响该事物的修改结果)
隔离性 isolation 一个事务的执行不能被其他事务干扰
一致性 consistency 理解为数据的完整性,通过原子性,持久性,隔离性来保证
事务控制
并发事务的问题
更新丢失:当两个事务更新同一行记录,会产生更新丢失现象
- 会滚覆盖
- 提交覆盖
脏读:一个事务读取到另一个事务未提交的数据
不可重复读:一个事务中,多次读取同一行数据,数据内容不一致。
a事务执行过程中,多次查询一条数据,b事务对该行数据进行了更新并提交
幻读:一个事务中,相同条件,多次查询,查询结果数不一致
a事务执行过程中,多次查询表数据,b事务对表数据进行删除/添加操作,并提交
演进过程
排队
排他锁
读写锁
MVCC
事务隔离级别
mysql数据库通过事务隔离级别来解决并发事务问题(更新丢失、脏读、不可重复读、幻读)
隔离级别类型
读未提交
Read Uncommitted 读未提交:解决了回滚覆盖类型的更新丢失,但可能发生脏读现象,也就是
可能读取到其他会话中未提交事务修改的数据。
读已提交
Read Committed 读已提交:只能读取到其他会话中已经提交的数据,解决了脏读。但可能发生
不可重复读现象,也就是可能在一个事务中两次查询结果不一致。
可重复读
Repeatable Read 可重复读:解决了不可重复读,它确保同一事务的多个实例在并发读取数据
时,会看到同样的数据行。不过理论上会出现幻读,简单的说幻读指的的当用户读取某一范围的数
据行时,另一个事务又在该范围插入了新行,当用户在读取该范围的数据时会发现有新的幻影行。
可串行化
Serializable 串行化:所有的增删改查串行执行。它通过强制事务排序,解决相互冲突,从而解决
幻度的问题。这个级别可能导致大量的超时现象的和锁竞争,效率低下。
数据库的事务隔离级别越高,并发问题就越小,但是并发处理能力越差(代价)。
读未提交隔离级别最 低,并发问题多,但是并发处理能力好。
事务隔离级别和锁的关系:
- 事务隔离级别是SQL92定制的标准,相当于事务并发控制的整体解决方案,本质上是对锁和MVCC使
用的封装,隐藏了底层细节。
- 锁是数据库实现并发控制的基础,事务隔离性是采用锁来实现,对相应操作加不同的锁,就可以防止其他事务同时对数据进行读写操作。
- 对用户来讲,首先选择使用隔离级别,当选用的隔离级别不能解决并发问题或需求时,才有必要在开发中手动的设置锁。
MySQL默认隔离级别:可重复读
Oracle、SQLServer默认隔离级别:读已提交
mysql隔离级别控制
查看MySQL当前数据库的事务隔离级别命令如下:
show variables like 'tx_isolation';
select @@tx_isolation;
设置事务隔离级别可以如下命令:
set tx_isolation='READ-UNCOMMITTED';
set tx_isolation='READ-COMMITTED';
set tx_isolation='REPEATABLE-READ';
set tx_isolation='SERIALIZABLE';
锁机制和实战
锁分类
操作粒度
表锁
页锁
行锁
操作类型
读锁/共享锁
写锁/排他锁
操作性能
乐观锁
悲观锁
行锁原理
记录锁
间隙锁
记录锁+间隙锁
悲观锁
指在数据处理过程中,将数据处于锁定状态,一般使用数据库的锁机制实现。
行锁、表锁、读锁、写锁、共享锁、排他锁都是悲观锁
乐观锁
乐观锁是相对于悲观锁而言,不是数据库提供的功能,需要开发者自己实现。
实现的关键点:冲突的检测
乐观锁实现原理:
- 使用版本字段(version),每次更新版本+1
- 使用时间戳,更新时比较记录时间是否一致
读锁
针对同一份数据,多个读操作可以同时进行
写锁
当前操作没有完成前,阻塞其他读锁和写锁
死锁解决方案
- 表锁死锁
- 行级锁死锁
- 共享锁转化为排他锁
- 死锁排查
- 查看死锁日志
通过show engine innodb status\G命令查看近期死锁日志信息。
使用方法:1、查看近期死锁日志信息;2、使用explain查看下SQL执行计划
- 查看锁状态变量
通过show status like’innodb_row_lock%‘命令检查状态变量,分析系统中的行锁的争夺
情况
Innodb_row_lock_current_waits:当前正在等待锁的数量
Innodb_row_lock_time:从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg: 每次等待锁的平均时间
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次锁的时间
Innodb_row_lock_waits:系统启动后到现在总共等待的次数
如果等待次数高,而且每次等待时间长,需要分析系统中为什么会有如此多的等待,然后着
手定制优化。