首页 > 数据库 >MySQL笔记

MySQL笔记

时间:2024-11-18 19:32:00浏览次数:1  
标签:语句 事务 笔记 索引 提交 MySQL 主键

数据类型

整型

create table test(
	a tinyint unsigned,
    b int(6) unsigned zerofill
)engine=innodb

int(N) 无论N是多少,int永远只占四个字节,N表示宽度,设置zerofill后不足的地方0补位

数据类型 字节数 带符号最小值 带符号最大值 不带符号最小值 不带符号最大值
TINYINT 1 -128 127 0 255
SMALLINT 2 -32768 32767 0 65535
MEDIUMINT 3 -8388608 8388607 0 16777215
INT 4 -2147483648 2147483647 0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807 0 18446744073709551616

浮点型

数据类型 字节数
float 4 单精度浮点型
double 8 双精度浮点型

float(M,N) M总位数,N精度

MySQL的浮点数精度只有53bit,大于53bit会被‘四舍五入’

定点型

decimal(M,N) 以字符串形式保存

日期类型

数据类型 字节数 格式
date 3 yyyy-MM-dd 存储日期值
time 3 HH:mm:ss 存储时分秒
year 1 yyyy
datetime 8 yyyy-MM-dd HH:mm:ss 存储日期+时间
timestamp 4 yyyy-MM-dd HH:mm:ss 时间戳

字符型

MySQL要求一个行的定义长度不能超过65535即64K (65535bytes) 1KB = 1024 Bytes

utf8编码下varchar(M) M=21844,utf8mb4 M=16383,gbk编码下varchar(M)最大的M=32765

varchar(M),当M范围为0<=M<=255时会专门有一个字节记录varchar型字符串长度,当M>255时会专门有两个字节记录varchar型字符串的长度,把这一点和上一点结合,那么65535个字节实际可用的为65535-3=65532个字节

char是固定长度字符串,其长度范围为0~255且与编码方式无关,无论字符实际长度是多少,都会按照指定长度存储,不够的用空格补足;varchar为可变长度字符串,在utf8编码的数据库中其长度范围为0~21844

char 处理数据时会将结尾的空格删除,varchar 不会

当varchar(M)的M大于某些数值时,varchar会自动转为text

  • M>255时转为tinytext
  • M>500时转为text
  • M>20000时转为mediumtext

事务

事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在 MySQL 中,事务支持是在引擎层实现的。MySQL 是一个支持多引擎的系统,但并不是所有的引擎都支持事务。原生的 MyISAM 引擎不支持事务

ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)

隔离性(Isolation)与隔离级别

SQL标准的事务隔离级别(隔离级别越高,效率越低)

隔离级别
读未提交(read uncommitted) 脏读(dirty read) 读取到未提交的事务
读提交(read committed) Oracle默认隔离级别 不可重复读(non-repeatable read) 数据前后不一致
可重复读(repeatable read) mySQL默认隔离级别 幻读 (phantom read) 多读取到数据,前后数量不一致
串行化(serializable )
show variables like 'transaction_isolation'; // 查看默认的隔离级别

事务的启动方式

  1. 显式启动事务语句, beginstart transaction。配套的提交语句是 commit,回滚语句是 rollback
  2. set autocommit = 0,这个命令会将这个线程的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接。(会导致意外的长连接)推荐 set autocommit = 1
  3. commit work and chain (提交事务并自动启动下一个事务,这样也省去了再次执行 begin 语句的开销)

begin/start transaction 命令不是一个事务的起点,在执行到它们之后的第一个操作 InnoDB 表的语句,事务才真正启动。如果你想要马上启动一个事务,使用 start transaction with consistent snapshot

为什么不推荐长事务,长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间。

MySQL 5.5 及以前的版本,回滚日志是跟数据字典一起放在 ibdata 文件里的,即使长事务最终提交,回滚段被清理,文件也不会变小。我见过数据只有 20GB,而回滚段有 200GB 的库。最终只好为了清理回滚段,重建整个库。

长事务的影响:长事务占用锁资源,也可能拖垮整个库

事务隔离实现

MVCC 多版本并发控制,

image

一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:

  • 版本未提交,不可见;
  • 版本已提交,但是是在视图创建后提交的,不可见;
  • 版本已提交,而且是在视图创建前提交的,可见。

更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读” (current read)

除了 update 语句外,select 语句如果加锁也是当前读。

-- 读锁(S 锁,共享锁)
select ... lock in share mode;
-- 写锁(X 锁,排他锁)
select ... for update;

InnoDB 的行数据有多个版本,每个数据版本有自己的 row trx_id,每个事务或者语句有自己的一致性视图。普通查询语句是一致性读,一致性读会根据 row trx_id 和一致性视图确定数据版本的可见性。

  • 对于可重复读,查询只承认在事务启动前就已经提交完成的数据;
  • 对于读提交,查询只承认在语句启动前就已经提交完成的数据;
  • 而当前读,总是读取已经提交完成的最新版本。

你也可以想一下,为什么表结构不支持“可重复读”?这是因为表结构没有对应的行数据,也没有 row trx_id,因此只能遵循当前读的逻辑。当然,MySQL 8.0 已经可以把表结构放在 InnoDB 字典里了,也许以后会支持表结构的可重复读。

索引

InnoDB索引模型

索引分为主键索引和非主键索引

主键索引 的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)

非主键索引 的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)

主键索引和非主键索引的区别在于,基于非主键索引的查询需要多扫描一棵索引树,这个过程称为回表

redo log 主要节省的是随机写磁盘的 IO 消耗(转成顺序写),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗

索引维护

自增主键不会触发叶子节点的分裂,非主键索引的叶子节点是主键的值,主键占用字节越大,普通索引占用空间也就越大。

优先使用自增字段做主键

NOT NULL PRIMARY KEY AUTO_INCREMENT

操作索引

alter table T drop index k;
alter table T add index(k);
// 重建主键索引不合理,会导致其他索引失效
alter table T engine=InnoDB;

索引优化

  • 覆盖索引
  • 索引下推(MySQL > 5.6)

索引失效场景

MySQL索引

MySQL 索引

MySQL中的锁

全局锁

对整个数据库实例加锁,命令 Flush tables with read lock (FTWRL) ,DML以及更新语句、更新类事务提交语句会被阻塞。

使用场景:全库逻辑备份(主从架构下,在主库做业务停摆,在从库做会造成主从延迟)

mysqldump –single-transaction
set global readonly=true // 方式二

表级锁

表锁,元数据锁(meta data lock,MDL)

lock tables … read/write unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

如何安全的给表加字段?

  • 查询 information_schema.innodb_trx 中的长事务,kill
  • NOWAIT/WAIT n 语法

行锁

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议

死锁处理策略

  • innodb_lock_wait_timeout
  • 死锁检测,innodb_deadlock_detect = on ,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行

死锁解决方法:调整语句顺序,控制客户端并发量

MySQL 锁

优化

SQL分析及数据库优化

附录

MySQL各版本新特性

5.6之前 MDL(5.5)
5.6 Online DDL并行复制
5.7
8

标签:语句,事务,笔记,索引,提交,MySQL,主键
From: https://www.cnblogs.com/imhui/p/18549791

相关文章

  • MySQL进阶:深入索引 - 空间索引
    ......
  • MySQL进阶:深入索引 - 函数和表达式索引
    ......
  • MySQL进阶:SQL高级技巧 - CTE和递归查询
    ......
  • MySQL脏读的演示
    MySQL脏读的演示1.查询和设置隔离级别showvariableslike'%isolation%';--或select@@tx_isolation;2.设置事务隔离级别需要退出MySQL再进入MySQL才能看到隔离级别的变化setglobaltransactionisolationlevel隔离级别;安全性:serializable>repeatableread>r......
  • 安装MySQL8数据库
    安装MySQL8MySQLCommunityServer社区版本,开源免费,自由下载,但不提供官方技术支持,适用于大多数普通用户。MySQLEnterpriseEdition企业版本,需付费,不能在线下载,可以试用30天。提供了更多的功能和更完备的技术支持,更适合于对数据库的功能和可靠性要求较高的企业客户。MySQLCl......
  • 来自笔记本的移植
    编译汇编代码到可执行文件并执行步骤假设文件名字是flag.asm在linux中,先nasm-felfflag.asm-oflag.o然后再ld-melf_i386-oflagflag.o然后就可以了,找个时间看看,nasm的用法修改aslr参数值:sudosysctl-wkernel.randomize_va_space=0#这是修改为0p.sendline(shellcod......
  • 笔记本(2)
    汇编代码的一些前置知识:;立即寻址方式moveax,11;将11赋值给eaxaddeax,114504;eax加上114504subeax,1;eax减去1;寄存器寻址方式movebx,0x36d;将0x36d赋值给ebxmovedx,ebx;将ebx的值赋值给edx;直接寻址方式movec......
  • 笔记本(3)
    我记得当初有写这个在某个地方啊==找不到了...就是一些二进制文件知识和exp中一些代码在libc中,就开始很常见的使用elf=ELF('/pwn')write_plt=elf.plt['write']......got.....got.........这两是用来查询[]内函数的plt和got的地址并赋值给左边变量,还有相似的main=elf.sym['mai......
  • Express的使用笔记8 引入验证中间件来给表单添加验证规则~
    前面已经将数据成功写入了数据库了,接下来就开始探讨接口传递参数的校验咯~自己封装虽然灵活,但也常常架不住有现成的,既灵活又方便,比如:express-valiation官方文档地址:https://express-validator.github.io/docs/guides/schema-validation先安装咯!npmiexpress-valiation引入......
  • 记录一些旧版本 MySQL 的问题与处理
    旧版本相关资源下载:https://downloads.mysql.com/archives/(以下版本号均为实测版本号,不代表同大版本下的其它小版本行为也会一致)1、MySQL5.1.46版本-使用命令或服务运行数据库时,不需要也不支持通过参数初始化数据库(下载的压缩包内已有初始数据)-默认的root用户密码为空,所......