数据库引擎

数据库引擎是存储、处理、保护数据的核心服务,利用数据库引擎可以快速处理数据库数据,从而满足要处理大规模数据的程序需求。

mysql数据库中常见的数据库引擎是Innodb和MyISAM。Innodb不支持全文索引(从5.6版本才开始支持),MyISam支持全文索引

什么是全文索引(类似站内搜索的功能,建立一个索引文件)什么是全文索引,为什么要使用全文索引

Innodb引擎提供对事务操作ACID(原子性、一致性、隔离性、持久性)的支持,还提供了行级索和外键约束,它设计的目标是处理大规模数据库,Mysql运行时Innodb会建立缓冲池,用于缓冲索引和数据。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在写操作较多或并发较大情况下,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。只有当where条件是索引的时候才会是行锁,如select * from table where id=1,id需要有索引

ACID

  • A  事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.
  • C 事务的一致性(Consistency):一致性指的是数据的状态,对于外部可见的是它的完成状态,而不是中间状态,比如a账号初始为100向b账号初始为0转100元,那么100,0是一个完成状态,最终的0,100是一个完成状态,但中间的0,0,即a减了100但b还没加上去,这是一个中间状态,对外是不可见的。
  • I 隔离性(Isolation):事务隔离性,是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.
  • D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚.

四种隔离级别

1.READ UNCIMMITTED(未提交读)脏读、不可重复读、幻象读

  事务中的修改,即使没有提交,其他事务也可以看得到,比如说上面的两步这种现象就叫做脏读,这种隔离级别会引起很多问题,如无必要,不要随便使用

  例子:还是售票系统,小明和小花是售票员,他们分别是两个不同窗口的员工,现在售票系统只剩下3张票,此时A来小华这里买3张票,B来小明买票,小华查到余票还有就给接了订单,就要执行第三步的时候,小明接到B的请求查询有没有余票。看到小华卖出了3张票,于是拒绝卖票。但是小华系统出了问题,第三步执行失败,数据库为保证原子性,数据进行了回滚,也就是说一张票都没卖出去。

  总结:这就是事务还没提交,而别的事务可以看到他其中修改的数据的后果,也就是脏读。

  

  2.READ COMMITTED(提交读)不可重复读、幻象读

  大多数数据库系统的默认隔离级别是READ COMMITTED,这种隔离级别就是一个事务的开始,只能看到已经完成的事务的结果,正在执行的,是无法被其他事务看到的。这种级别会出现读取旧数据的现象

  例子:还是小明小华销售员,余票3张,A来小华那里请求3张订票单,小华接受订单,要卖出3张票,上面的销售步骤执行中的时候,B也来小明那里买票,由于小华的销售事务执行到一半,小明事务没有看到小华的事务执行,读到的票数是3,准备接受订单的时候,小华的销售事务完成了,此时小明的系统变成显示0张票,小明刚想按下鼠标点击接受订单的手又连忙缩了回去。

  总结:这就是小华的事务执行到一半,而小明看不到他执行的操作,所以看到的是旧数据,也就是无效的数据

  3.REPEATABLE READ(可重复读)幻象读

       mysql通过MVCC(多版本并发控制)实现了可重复读,通过每一行数据记录后增加了两个隐藏列来实现的,分别表示创建时间和删除时间,但其中存储的是版本号。进行插入时会在创建时间列插入一个当前事务的版本号;更新时会复制一条当前数据,之后在新数据记录内进行更新操作,并且将当前事物版本号作为新数据的创建时间,然后将当前事物版本号放入原数据的删除时间内表示原数据被删除;删除数据时直接将当前删除事务版本号放入删除时间内;而查询时,寻找创建时间小于等于当前事务,且删除时间大于当前事务版本的记录,就算其他新事务更新或删除了原数据也不会对当前事务查询产生影响

MySQL在RR下到底有没有修复幻读

mysql串行化防幻读原理_透彻解读mysql的可重复读、幻读及实现原理

   REPEATABLE READ解决了不可重复读的问题,该级别保证了每次查询同一条记录的结果是一致的,也就是上面说的读了旧数据的问题,但是却无法解决另一个问题,幻行,顾名思义就是突然蹦出来的行数据。指的就是某个事务在读取某个范围的数据,但是另一个事务又向这个范围的数据去插入数据,导致多次读取的时候,数据的行数不一致。

  例子:销售部门有规定,如果销售记录低于规定的值,要扣工资,此时经理在后端控制台查看了一下小明的销售记录,发现销售记录达不到规定的次数,心里暗喜,准备打印好销售清单,理直气壮和小明提出,没想到打印出来的时候发现销售清单里面销售数量增多了几条,刚刚好达到要求,气的经理撕了清单纸。原来是小明在就要打印的瞬间卖出了几张票,因此避过了减工资的血光之灾。

  总结:虽然读取同一条数据可以保证一致性,但是却不能保证没有插入新的数据

  4.SERIALIZABLE(可串行化)

  SERIALIZABLE是最高的隔离级别,它通过强制事务串行执行(注意是串行),避免了前面的幻读情况,由于他大量加上锁,导致大量的请求超时,因此性能会比较底下,再特别需要数据一致性且并发量不需要那么大的时候才可能考虑这个隔离级别

在spring注解@Transactional中默认的隔离级别是ISOLATION_DEFAULT,即使用数据库的事物隔离级别,mysql默认的隔离级别是可重复读,但项目中一般都是使用读已提交

spring @Transactional事务的传播行为,有七种

1.TransactionDefinition.PROPAGATION_REQUIRED
方法需要在事务中执行,如果当前存在事务,则在当前事务中运行,如果没有事务则新建一个
2.TransactionDefinition.PROPAGATION_SUPPORTS
方法不需要在事务中运行,如果当前存在事务,则在事务中运行
3.TransactionDefinition.PROPAGATION_MANDATORY
方法必须在事务中运行,如果当前不存在事务则抛出异常
4.TransactionDefinition.PROPAGATION_REQUIRES_NEW
方法必须在自己的事务中 运行,如果当前存在事务,则将当前事务挂起,新建一个事务执行该方法
5.TransactionDefinition.PROPAGATION_NOT_SUPPORTED
方法不应该在事务中运行,如果当前存在事务,则方法运行期间先将事务挂起
6.TransactionDefinition.PROPAGATION_NEVER
方法不应该在事务中运行,若当前存在事务则抛出异常
7.TransactionDefinition.PROPAGATION_NESTED
嵌套事务,外层事务提交内层事务才会提交,外层事务回滚内层事务也会回滚,但内层事务回滚不会导致外层事务。
@Transaction默认是使用的TransactionDefinition.PROPAGATION_REQUIRED

MyIASM引擎

  MyIASM是MySQL默认的引擎(5.5之前,之后变成了InnoDB),但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和Innodb不同,MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。

Innodb和Myiasm锁的一些小补充

Innodb通过给索引上锁来实现行锁,因此只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁
假如现在有city表 id code name,id为主键,code有普通索引
Session1
SELECT * FROM city WHERE id=14  FOR UPDATE;
Session2
SELECT * FROM city WHERE id=13 FOR UPDATE;
这样不会锁冲突,但是如果session2也是id=14就会冲突

MyISAM表级锁模式:
在执行查询语句(SELECT)前,会自动给涉及的表加读锁,在执行更新操作,UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁
表共享读锁 (Table Read Lock):不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
表独占写锁 (Table Write Lock):会阻塞其他用户对同一表的读和写操作;

InnoDB 实现了以下两种类型的行锁:
对于select语句,innodb不会加锁select … lock in share mode 是加共享锁;对于update和delete、insert语句,会自动加排他锁, select … for update 也会加排他锁
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁,但是可以使用select进行查询

Innodb中还提供了间隙锁,当我们用范围条件而不是相等条件检索数据,并请求共享或排它锁时,innodb会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录就叫做"间隙锁" 
Session1
update city set name =“123” WHERE id>17 
Session2
SELECT * FROM city WHERE city_id=18 FOR UPDATE;
或delete from city where id=19;
就会报错即使18、19不存在
https://blog.csdn.net/diankuozhi9810/article/details/102302415

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值