一、存储引擎介绍
MySQL 中的存储引擎以及支持事务,和不支持事务的存储引擎
1. 存储引擎的概念:
在mysql中的数据用各种不同的技术存储在文件(或内存)中。
这些技术中的每一种技术都使用不同的存储机制,索引 技巧,并且最终提供广泛的不同的功能和能力。
可以通过选择不同的技术,可以获得额外的速度或功能,从而改善应用的整体功能。
这些不同的技术以及配套的相关功能在mysql中被称为存储引擎(也称为表类型)。
2. MySQL 查看存储引擎
MySQL支持的存储引擎很多,可以在MySQL客户端输入以下命令查看mysql支持的存储引擎的详细信息。
show engines;
3. 存储引擎分类
1. MyISAM:
拥有较高的插入,查询速度,但不支持事务。
2. InnoDB:
5.5版本后Mysql的默认数据库,事务型数据库的首选引擎,支持ACID事务,支持行级锁定。
3. BDB:
源自Berkeley DB,事务型数据库的另一种选择,支持COMMIT和ROLLBACK等其他事务特性
4. Memory :
所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在Mysql重新启动时丢失
5. Merge :
将一定数量的MyISAM表联合而成一个整体,在超大规模数据存储时很有用
6. Archive :
非常适合存储大量的独立的,作为历史记录的数据。因为它们不经常被读取。Archive拥有高效的插入速度,但其对查询的支持相对较差
7. Federated:
将不同的Mysql服务器联合起来,逻辑上组成一个完整的数据库。非常适合分布式应用
8. Cluster/NDB :
高冗余的存储引擎,用多台数据机器联合提供服务以提高整体性能和安全性。适合数据量大,安全和性能要求高的应用
9. CSV:
逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个.CSV文件。这是一种普通文本文件,每个数据行占用一个文本行。CSV存储引擎不支持索引。
10. BlackHole :
黑洞引擎,写入的任何数据都会消失,一般用于记录binlog做复制的中继
11. 自定义
Mysql的存储引擎接口定义良好,开发者可以通过阅读文档编写自己的存储引擎。
二、什么是事务
1. 概述:
事务(Transaction):一般是指要做的或所做的事情。
在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。
事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。
事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
2. 概念
在关系向数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
(前面说过了,MySQL是关系型数据库的一种)
事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。
整个单独单元作为一个不可分割的整体,如果单元中某条SQL语句一旦执行失败或产生错误,整个单元将会回滚。
所有受到影响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事务被顺利执行。
即开始事务后执行的所有SQL都是一个整体,一个单元,要么都执行,要么都不执行。这里不执行的意思就row back即回滚,就是回到事务执行前的状态。
3. 特性(事物的四个属性:ACID)
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
1. 原子性(atomicity):
一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
简单来说:要么都成功,要么都失败。
2. 一致性(consistency):
事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
简单来说:事务前后的数据完整性要保持一致。
3. 隔离性(isolation):
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
简单来说:事务一旦提交就不可逆转,被持久化到数据库中。
4. 持久性(durability):
持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
简单来说:事务产生多并发时,互不干扰。
三、事物的类型
1. 手动事务
手动事务允许显式处理若干过程,这些过程包括:开始事务、控制事务边界内的每个连接和资源登记、确定事务结果(提交或中止)以及结束事务。
尽管此模型提供了对事务的标准控制,但它缺少一些内置于自动事务模型的简化操作。
例如,在手动事务中数据存储区之间没有自动登记和协调。
此外,与自动事务不同,手动事务中事务不在对象间流动。
如果选择手动控制分布式事务,则必须管理恢复、并发、安全性和完整性。
也就是说,必须应用维护与事务处理关联的 ACID 属性所需的所有编程方法。
2. 自动事务
.NET 页、XML Web services方法或 .NET Framework 类一旦被标记为参与事务,它们将自动在事务范围内执行。
可以通过在页、XML Web services 方法或类中设置一个事务属性值来控制对象的事务行为。
特性值反过来确定实例化对象的事务性行为。
根据声明特性值的不同,对象将自动参与现有事务或正在进行的事务,成为新事务的根或者根本不参与事务。
声明事务属性的语法在 .NET Framework 类、.NET 页和 XML Web services 方法中稍有不同。
声明性事务特性指定对象如何参与事务,如何以编程方式被配置。
尽管此声明性级别表示事务的逻辑,但它是一个已从物理事务中移除的步骤。
物理事务在事务性对象访问数据库或消息队列这样的数据资源时发生。
与对象关联的事务自动流向合适的资源管理器,诸如 OLE DB、开放是数据库连接 (ODBC) 或 ActiveX 数据对象 (ADO) 的关联驱动程序在对象的上下文中查找事务,并通过分布式事务处理协调器 (DTC) 在此事务中登记。整个物理事务自动发生。
三、隔离产生的问题
1. 事物的隔离级别
1. 读未提交数据(Read uncommitted)
定义:
就是一个事务读取到其他事务未提交的数据,是级别最低的隔离机制。
缺点:
会产生脏读、不可重复读、幻读。
案例:
以前交易所炒股的时候,股民老王购买了5000股,操作员操作录入(此时开启事务),操作时手误,多输入了一个0,数据保存但是未提交。此时老王查询自己的持股信息,发现自己居然有50000股,瞬间血压升高,昏倒在地。然后操作员发现自己录入错误,修改成正确的信息,录入完成(事务结束)。老王被救醒后,哆嗦这查询自己的持股,发现只有5000,没有增减,他之前看到的就是脏读数据。
解决方案:
采用更高级的隔离机制,如提交读。
2. 读已提交数据(Read committed)
定义:
就是一个事务读取到其他事务提交后的数据。Oracle默认隔离级别。
缺点:
会产生不可重复读、幻读。
案例:
股市升高后,老王查看自己持有5000股,就想卖掉4000股,在老王卖股票的时候,老王的老婆看股市太高,就登录老王的账号,卖掉3000股。当老王想卖股票时,发现自己只有2000股,不是之前看到的5000股,这就是不可重复读问题。
解决方案:
采用更高级的隔离机制,如可重复读。
3. 可重复读(Repeatable read)
定义:
就是一个事务对同一份数据读取到的相同,不在乎其他事务对数据的修改。MySQL默认的隔离级别。
缺点:
会产生幻读。
问题解读:
股市忽涨忽跌,老王焦虑不安,按捺不住,想把持有的多种股票全部抛掉。与此同时,老外老婆听信砖家所言,使用老王的账号买了某只神股。老王抛掉所有股票后,查看自己的持股,猛然发现自己居然还持有一只股票,瞬间觉得一脸懵逼,这就是幻读导致。
解决方案:
采用更高级的隔离机制,序列化。
4. 串行化(Serializable)
定义:
事务串行化执行,隔离级别最高,牺牲了系统的并发性。
缺点:
可以解决并发事务的所有问题。但是效率地下,消耗数据库性能,一般不使用。
5. 总结
2. 隔离级别会产生的问题介绍
1. 脏读:
指一个事务读取了另外一个事务未提交的数据。
2. 不可重复读:
在一个事务内读取表中的某一行数据,多次读取结果不同。
(这个不一定是错误,只是某些场合不对)
3. 虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
(一般是行影响,多了一行)
四、执行事务
绍事务的语法:
1. 开启事务start transaction,可以简写为 begin
2. 然后记录之后需要执行的一组sql
3. 提交commit
4. 如果所有的sql都执行成功,则提交,将sql的执行结果持久化到数据表内。
5. 回滚rollback
6. 如果存在失败的sql,则需要回滚,将sql的执行结果,退回到事务开始之时
7. 无论回滚还是提交,都会关闭事务!需要再次开启,才能使用。
8. 还有一点需要注意,就是事务只针对当前连接。
1. mysql 自动开启事务提交
SET autocommit=0 -- 关闭 SET autocommit=1 -- 开启(默认的)
2. 手动处理事务
SET autocommit =0 -- 关闭自动提交
3. 事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的SQP都在同一个事务内 INSERT XX INSERT XX
4. 提交 : 持久化(成功)
COMMIT
5. 回滚: 回到原来的样子(失败)
ROLLBACK
6. 事务结束
SET autocommit = 1 -- 开启自动提交
7. 其他
SAVEPOINT 保存点名称 -- 设置一个事务的保存点 ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点 RELEASE SAVEPOINT 保存点 -- 删除保存点
五、模拟场景
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci USE shop CREATE TABLE `account`( `id` INT(3) NOT NULL AUTO_INCREMENT, `name` VARCHAR(30) NOT NULL, `money` DECIMAL(9,2) NOT NULL, PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO account(`name`,`money`) VALUES('A',2000),('B',10000)
模拟转账:事务
SET autocommit = 0; -- 关闭自动提交 START TRANSACTION -- 开启事务(一组事务) UPDATE account SET money = money-500 WHERE `name` = 'A' -- A 转账给B UPDATE account SET money = money+500 WHERE `name` = 'B' -- B 收到钱 COMMIT ; -- 提交事务 ROLLBACK ; -- 回滚 SET autocommit=1 -- 恢复默值