事务与并发写
某个正在更新的记录在提交或回滚前不能被其他事物同时更新
先加锁后修改 等待锁释放
事物的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这类文件中
来源:CSDN
作者:小白爱Python
链接:https://blog.csdn.net/weixin_45010894/article/details/103595442