事务

我与影子孤独终老i 提交于 2019-12-19 03:10:21

事务与并发写

某个正在更新的记录在提交或回滚前不能被其他事物同时更新
先加锁后修改 等待锁释放

事物的ACID

原子性Atomic: 要么全部执行,要么全部不执行,中途数据库发生异常,未提交的事物都被回滚
一致性Consistency: 数据库从一种正确状态转为另一种正确状态,数据库在修改时保证数据的正确性合理性一致性
隔离性Isolation 事务正确提交完成前,中间的任何数据变化对其他的事物都是不可见的
持久性Durability: 事物一旦提交就永久保存…数据库写在事务日志异步更新到磁盘,使用事务日志持久化实现只要是性能方面的考虑

四种隔离级别

1读未提交:读到未提交的数据
2读已提交:两次读取到的数据不一致(不可重复读)
3可重复读 mysql默认隔离级别
4串行化:读写数据会锁表.并发性能低

并发事务问题

脏读,读取他人未提交事物
不可重复读:其他事务对数据进行了修改
幻读:其他事务对数据进行了增加或删除

查看数据库默认的隔离级别

select @@tx_isolation;

默认级别可重复读

REPEATABLE-READ

设置隔离级别为–读未提交

set tx_isolation ='read-uncommitted';
select @@tx_isolation;
READ-UNCOMMITTED

读已提交 --解决脏读

set tx_isolation ='read-committed';
select @@tx_isolation;
READ-COMMITTED

可重复读 --事物提交之前,不受他人操作的影响 解决脏读,不可重复读,会出现幻读

set tx_isolation ='repeatable-read';
select @@tx_isolation;
REPEATABLE-READ

串行化–解决脏读,不可重复读,幻读
事情提交之前,其他事物不可修改数据

set tx_isolation ='serializable';
select @@tx_isolation;
SERIALIZABLE

开启事物

start transaction ;
begin ;

提交事物

commit ;

事物回滚
事务回滚是实现事务原子性的重要功能
事务一旦回滚成功,该事务的数据变化就无法在恢复回来,除非重新执行

rollback ;

事物回滚的实现
数据表在修改数据时,将表文件修改前的数据放在回滚段(rollback segment)中,当表文件中修改数据提交后,回滚段为空,如果修改字段回滚,则将回滚段的数据拷贝回原来的表文件中
回滚段也帮助实现事务的隔离性

清空表数据
truncate table name

commit为提交为防止
回滚到保存点savepoint name
rollback to name
autocommit可以在session级别设置
每个dml操作都自动提交
ddl永远是自动提交,无法通过rollback回滚
(当alter表时,之前所有插入的数据即使关闭自动提交,重启数据库后数据都已提交)

show global variables like '%auto%'
关闭当前自动提交
set session autocommit=0;
show session variables like '%autocommit%'

innodb行级锁

  • 写不阻塞读
  • 不同行间的写互相不阻塞
  • 并发性能好

innoDB锁的原理

锁用来解决并发引发的问题

1共享锁
S锁,读锁,当开启共享锁其他人可以读但不能修改
获取共享锁

begin ;
select *from book where bid=2 lock in share mode ;

2排他锁
x锁,写锁(与任何锁不共存)
修改数据未提交时,他人无法操作

update book set name="三生三世十里桃花" where bid=3;

获取排他锁
范围之内不能插入数据

select *from book where bid between 1 and 50 for update ;

innoDB行锁是给索引上锁,无索引上表锁
3意向共享锁
IS

4意向排它锁
IX
5自增锁
主键id
未提交的id也会丢失
回滚10十条数据,下一次插入的数据id为11
6临键锁
<,>,between-and
范围之内无法操作

select *from book where bid between 1 and 50 for update ;

7间隙锁
gap lock 消灭幻读
间隙锁锁住索引区间,避免插入

  • innodb消灭幻读仅仅为了确保statement模式replicate的主从一致性
  • 当18 19 22 22 22 25 27中22上排他锁
  • 则[19,25]中的数字都上间隙锁,20,23等这些数字无法插入

8记录锁

隔离级别与锁之间的关系
脏读--------------------排他锁(X)
不可重复读-----------共享锁
幻读--------------------临键锁

数据库

计算机处理和存储的一切信息都是数据
数据库是计算机系统中用于存取数据的程序
数据库优势
事物控制,持久化和数据安全,查询数据需求逻辑复杂
关系型数据库
mysql,oracle,SqlServer,postgreSQl
非关系型数据库
hadoop,mongoDB,redis,Cassandra

数据库–关系型数据库

mysql
最流行,开源,并不是最先进

开源:
基于GPL协议开放源代码
社区版本完全免费
代码允许自由地进行修改

mysql具备关系型数据库核心功能但是特性并不繁多
架构设计趋于精简

计算机程序锁

  • 控制对共享资源进行并发访问
  • 保护数据的完整性和一致性

数据库中的锁

lock latch/mutex
对象 事务 线程
保护 数据库逻辑内容 内存数据结构
持续时间 事务过程中 临界资源抢夺

事务锁粒度

  • 行锁
    innodb,oracle
  • 页锁
    sql server
  • 表锁
    myisam memory

innodb存储引擎中的锁模式与粒度

  • 四种基本锁模式
  • 共享锁(S) 读锁 --行锁
  • 排他锁(X)写锁----行锁
  • 意向共享锁(IS)–表级
  • 意向排他锁(IX)—表级

意向锁

  • 意向锁总是自动先加,并且意向锁自动自动释放
  • 意向锁提示数据库这个session将要在接下来施加何种锁
  • 意向锁和X/S锁级别不同,会阻塞全表级别的X/S锁,其他锁不会阻塞

innodb行锁的实现

通过索引项加锁实现

  • 只有条件走索引才能实现行级锁
  • 索引上有重复值,可能锁住多个记录
  • 查询有多个索引可以走,可以对不同的索引加锁
  • 是否对索引加锁实际上取决于mysql执行计划
  • 自增主键做条件更新,性能最好

死锁dead lock

两个连接相互等待
a占用id=1的资源,请求修改id=4
b占用id=4的资源,请求修改id=1

死锁解决办法

数据库自动解决
数据库挑选冲突事务中的回滚代价较小的事物回滚

死锁预防
单表死锁可以根据批量更新里的更新条件排序
可能冲突的跨表事务尽量避免开发
尽量缩短事务长度,单布事务永远 不会发生死锁

###排查死锁

  • 了解触发死锁的sql所在事务的上下文
  • 根据上下文语句加锁的范围来分析存在争用的记录
  • 通常改善死锁的主要方法:
    1对同一个表的操作根据加锁条件进行排序
    2拆分长事务
    找到id
select trx_mysql_thread_id,trx_state,now()-trx_started,trx_rows_locked from information_schema.innodb_trx;

kill 1

业务逻辑中的锁

悲观锁
认为任何并发修改都会造成业务逻辑错误,从一开始就锁定所有要操作的记录,直到最终才释放
乐观锁
只在最终修改提交之前判断是否成功,就可以保证数据安全有效

事物与锁

什么时候需要事物和锁

  • 需要保证操作’原子性’
  • 需要利用’锁’避免业务纠纷
  • for update 人工加锁

begin;
1
2
3
4

10
commit;
大事物的好处

坏处
不利于并发

innodb缓存池(buffer POOL)
innodb缓存池缓存的是数据块
innodb表如果数据不存在于缓存池中,那么数据读取的时候首先要将数据读入到缓存池

innodb事务日志的持久化
当数据库异常宕机后,事务日志用来重做已经提交单未持久化的数据
利用事务日志先写实现的持久化对innodb写数据的效率有很大的提升

innodb回滚
innodb回滚段存放在ibdata这类文件中
事务在修改数据前,会先在该事务回滚段中记录数据修改前的状态
innodb回滚段放在ibdata这类文件中

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!