MySQL学习笔记(六)------事务和索引

MySQL学习笔记(六)------事务和索引

事务

什么是事务?

  • 将一组SQL放在同一个批次中去执行

  • 特点:要么都成功,要么都失败

  • 原则:ACID原则:原子性,一致性,隔离性,持久性 (脏读,幻读…)

原子性(Atomicity)

​ 是指一个事务要么全部执行,要么不执行,也就是说一个事务不可能只执行了一半就停止了。

  • 比如A给B支付200元,这个事务可以分成两个步骤:1、A减少200元,2、B收到200元。不可能A少了,而B没有多。这两步必须同时完成,要么就都不完成。不能只发生一个动作。

一致性(Consistency)

​ 是指事务的运行并不改变数据库中数据的一致性。

  • 最终一致性:A有1000,B有200,那么无论怎么更改,AB总和都有1200

隔离性(Isolation)

​ 事务的隔离性也称作独立性,是指两个以上的事务不会出现交错执行的状态。因为这样可能会导致数据不一致,更加具体的来讲,就是事务之间的操作是独立的。

  • 如果隔离性出现错误,会有很多问题产生

持久性(Durability)

​ 事务的持久性是指事务执行成功以后,该事务对数据库所作的更改便是持久的保存在数据库之中,不会因为外界原因导致数据丢失。事务一旦提交不可逆。

  • 例如:操作前—A:1000,B:200;操作后—A:800,B:400
  • 如果在操作前(事务没有提交),服务器断电,那么重启后,数据应为A:1000,B:200
  • 如果在操作后(事务已经提交),服务器断电,那么重启后,数据应为A:800,B:400

不考虑隔离性会发生什么问题?

脏读
  • 指一个事务读取了另一个事务没有提交的数据
不可重复读
  • 在一个事务内读取某一行数据时,多次读取结果不同。(不一定是个错误,只是某些场合不对)
  • 例如:开始读取数据时B为300,生成表单时,B收入100,此时读出B的数据为400
幻读(虚读)
  • 指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致(一般是行的影响,多了一行)
  • 例如:开始读取数据时,数据表中只有A,B两行;生成表单时,新插入了数据C,此时读出数据为A,B,C三行

四种隔离级别

读未提交(Read uncommitted):
  • 这种事务隔离级别下,select语句不加锁。

  • 此时,可能读取到不一致的数据,即“读脏 ”。这是并发最高,一致性最差的隔离级别。

读已提交(Read committed):
  • 可避免脏读的发生。

  • 在互联网大数据量,高并发量的场景下,几乎不会使用上述两种隔离级别。

可重复读(Repeatable read):
  • MySql默认隔离级别。

  • 可避免脏读 、不可重复读的发生。

串行化(Serializable ):
  • 可避免脏读、不可重复读、幻读的发生。
级别
  • 以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别
  • 级别越高,执行效率越低

基本语法

  • MySQL时默认开启事务自动提交的
SET autocommit = 0;   /*关闭*/
SET autocommit = 1;   /*开启*/
  • 手动处理事务(关闭自动提交)
  • 事务开启
START TRANSACTION 
  • 提交一个事务给数据库
COMMIT
  • 将事务回滚:回到本次事务开始时的样子
ROLLBACK
  • 手动处理事务结束(开启自动提交)

  • 保存点(了解)(一个事务可以有多个保存点)

SAVEPOINT 保存点名称 -- 设置一个事务保存点
ROLLBACK TO SAVEPOINT 保存点名称 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名称 -- 撤销已有保存点

模拟转账

CREATE DATABASE `shop`CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE `account` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NOT NULL,
  `cash` DECIMAL(9,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
 
INSERT INTO account (`name`,`cash`)
VALUES('A',2000.00),('B',10000.00)
 
-- 转账实现
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION;  -- 开始一个事务,标记事务的起始点
UPDATE account SET cash=cash-500 WHERE `name`='A';
UPDATE account SET cash=cash+500 WHERE `name`='B';
COMMIT; -- 提交事务
--rollback;
SET autocommit = 1; -- 恢复自动提交

索引

  • MySQL官方对索引的定义为:索引是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:
  • 索引是数据结构
  • 常规命名方式:id_表名_字段名

分类

主键索引(Primary Key)
  • 唯一标识,主键不可重复
  • 只能有一个列作为索引
唯一索引(Unique Key)
  • 避免重复的列出现,唯一索引可以重复
  • 多个列都可以标识为唯一索引
常规索引(Key/Index)
  • 默认的,可以用index或key关键字来设置
全文索引(FullText)
  • 在特定的数据库引擎下才有
  • 快速定位数据

索引的使用

  • 在创建表的时候给字段增加索引
  • 创建完毕后,增加索引

基础命令

  • 显示所有的索引信息
show index from 表名
  • 已知表增加一个索引
alter table `表名` add 索引类型 index `索引名`(`列名`)
alter table `student` add fulltext index `studentname`(`studnetname`)
--给某个表中的某个字段加一个索引
CREATE 索引类型 INDEX 索引名 ON 表名 (字段名[(长度)] [ASC |DESC]) ;
  • 创建表时增加索引
CREATE TABLE 表名 (
                字段名1  数据类型 [完整性约束条件…],
                字段名2  数据类型 [完整性约束条件…],
                索引类型   INDEX | KEY
                [索引名]  (字段名[(长度)]  [ASC |DESC])
                );
  • 删除索引
DROP INDEX 索引名 ON 表名字;          --删除非主键索引
ALTER TABLE 表名 DROP PRIMARY KEY;   --删除主键索引
  • 显示索引信息
SHOW INDEX FROM student;
  • 分析sql执行的状况
explain select * from student;  --非全文索引
explain select * from student where match(studentname) against('刘'); ---全文索引(在数据量很少的时候没有用)

测试索引

建表
CREATE TABLE `app_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT '' COMMENT '用户昵称',
  `email` varchar(50) NOT NULL COMMENT '用户邮箱',
  `phone` varchar(20) DEFAULT '' COMMENT '手机号',
  `gender` tinyint(4) unsigned DEFAULT '0' COMMENT '性别(0:男;1:女)',
  `password` varchar(100) NOT NULL COMMENT '密码',
  `age` tinyint(4) DEFAULT '0' COMMENT '年龄',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='app用户表'
插入100万条数据(不用掌握)
DROP FUNCTION IF EXISTS mock_data;
DELIMITER $$   --写函数之前必须要写,当作标志
CREATE FUNCTION mock_data()    --创建一个函数
RETURNS INT     --返回值
BEGIN          --函数体
  DECLARE num INT DEFAULT 1000000;
  DECLARE i INT DEFAULT 0;
  WHILE i < num DO     --循环操作
  	INSERT INTO app_user(`name`, `email`, `phone`, `gender`, `password`, `age`)
    VALUES(CONCAT('用户', i), '123456897@qq.com', CONCAT('18', FLOOR(RAND()*(999999999-100000000)+100000000)),FLOOR(RAND()*2),UUID(), FLOOR(RAND()*100));
    --concat('用户',i),拼接用户名为用户i
    --floor取整 rand随机数(有小数,所以要用floor取整)
   SET i = i + 1;      --i自增操作
  END WHILE;           --循环结束
  RETURN i;
END;
SELECT mock_data();
创建常规索引
CREATE INDEX idx_app_user_name ON app_user(name);

索引的用途

  • 在有索引的情况下,查询数据更加高效,直接定位需求数据,没有索引需要遍历所有的数据
  • 索引在数据量比较小的时候,用处不大;在数据量大的时候,提升效率十分明显

索引原则

  • 索引不是越多越好
  • 不要对经常变动的数据加索引
  • 小数据量的表不需要加索引
  • 索引一般加在常用来查询的字段上(提高查询速度)

索引的数据类型(拓展)

  • Hash类型的索引
  • Btree类型的索引:InnoDB的默认数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值