默认情况下,每个客户端连接都会在服务器进程中拥有一个线程,该连接的查询只会在这个单独的线程中执行。服务器维护了一个缓存区(线程池),用于存放已就绪的线程,因此不需要为每个新点连接创建或销毁线程。
身份验证是基于用户名、主机名、密码,如果以跨传输层安全(TLS)的方式连接,可以使用X.509认证证书。客户端连接成功后,服务器会继续严重该客户端是否具有其发出的每个查询的权限,eg:表查询权限。
重写查询、决定表的读取顺序、选择合适的索引等
只要有多个查询需要同时修改数据,就会产生并发控制问题。MySQL两个级别的并发控制:服务器级别和存储引擎级别
共享锁(读锁)、排他锁(写锁)
原则:尽量只锁定包含需要修改的部分数据,让锁的数据量最小化。
加锁也需要消耗资源,锁的各种操作,包括获取锁、检查锁是否空闲、释放锁等
锁定策略是锁开销和数据安全性之间的一种平衡,一般是在表中施加行级锁。锁是数据库实现一致性保证的方法。
表锁:MySQL中最基本开销最小的锁策略;
行级锁:可以最大程度地支持并发处理,也带来了最大的锁开销。行级锁是在存储引擎中实现的。
事务就是一组SQL语句,作为一个工作单元以原子方式进行处理,要么全部执行成功,要么全部执行失败。
start transaction开启事务
ACID:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability),在此就不展开了。
ANSI SQL标准定义了4种隔离界别,目标:定义在事务内外可见和不可见的更改的规则。较低的隔离级别通常允许更高的并发性,开销也更低。
read uncommitted(未提交读):在事务中可以查看其他事务中没有提交的修改。
脏读:读取未提交的数据。
read committed(提交读):一个事务可以看到其他事务在它开始之后提交的修改,但在该事务提交之前,其所做的任何修改对其他事务都是不可见的。提交读是Oracle采用的隔离级别。
pepeatable read(可重复读):解决了提交读级别不可重复读问题,保证了在同时一个事务中多次读取相同行数据的结果是一样的。理论上无法解决幻读。可重复读时MySQL默认的隔离级别。
幻读:当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围记录时,就会产生幻行。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC)解决了幻读问题。
serializable(可串行化):是最高的隔离级别,在读取每一行数据都会加锁,可能导致大量的超时和锁争用问题。除非需要严格确保数据安全且可以接受并发性能下降时使用。
隔离级别 |
脏读 |
不可重复读 |
幻读 |
加锁读 |
未提交读 |
是 |
是 |
是 |
否 |
提交读 |
否 |
是 |
是 |
否 |
可重复读 |
否 |
否 |
是 |
否 |
可串行化 |
否 |
否 |
否 |
是 |
死锁是指两个或多个事务相互持有和请求相同资源上的锁,产生循环依赖。
当多个事务试图以不同的顺序锁定资源时导致死锁;当多个事务锁定相同的资源时,也可能会发生死锁。
数据库系统实现了各种死锁检测和锁超时机制。
InnoDB检测到循环依赖后会立即返回一个错误信息,死锁的表现为非常缓慢的查询。InnoDB处理死锁的方式是将持有最少行排他锁的事务回滚。
锁的行为和顺序与存储引擎相关。产生死锁有双重原因:有些事因为真正的数据冲突,这种情况很难避免,有些则是完全由于存储引擎的实现方式导致的。
事务日志有助于提高事务的效率。存储引擎只需要更改内存中的数据副本,而不用每次修改磁盘中的表。事务日志采用的是追加写操作,在硬盘中一块区域内的顺序I/O(提高效率),最后有一个后台进程在某个时间去更新硬盘中的表。大多数使用的预写式日志的存储引擎修改数据最终需要写入磁盘两次。
InnoDB是MySQL的默认事务型存储引擎,它是为处理大量短期事务而设计的,这些事务通常是正常提交的,很少被回滚。
InnoDB使用MVCC来实现高并发性,实现了4个隔离级别,默认为可重复读。并通过间隙锁策略防止在可重复读上的幻读:InnoDB不只锁定在查询中涉及的行,还会对索引结构的间隙进行锁定,以防止幻行被插入。
InnoDB表基于聚簇索引构建的,聚簇索引提供了非常快的主键查找,如果表中的索引较多,主键应当尽量小。
InnoDB内部做了很多优化,包括从磁盘预读取数据的可预测性预读、能够自动在内存中构建哈希索引以进行快速查找的自适应哈希索引,以及用于加速插入操作的插入缓冲区。
InnoDB可以通过一些机制和工具支持真的的在线“热”备份。
MySQL8.0,就地更改模式的机制允许在不使用完整表锁和外部工具的情况下进行特定的表更改操作,大大提高了MySQL InnoDB表的可操作性。
JSON类型在5.7版本后引入InnoDB,实现了JSON文档自动验证、优化了存储以允许快读读取。8.0版本后,增加了在JSON数组上定义多值索引的能力,将常访问的模式匹配到可以映射JSON文档值的函数这一特性,可以进一步加快对JSON类型的读取访问查询。
8.0删除了基于文件的表元数据存储,使用InnoDB表存储的数据字典中。
8.0引入了原子数据定义更改,数据定义语句要么全部成功完成,要么全部失败回滚。这是通过创建DDL特定的Undo日志和Redo日志来实现的。