MySQL


MySQL事务

事务是指逻辑上的一组操作,组成这个操作的各个单元,要么全部成功,要么全部失败回滚

  • 支持连续SQL的集体成功或集体撤销。

  • 事务是数据库在数据数据完整性的一个功能。

  • 需要利用 InnoDB 或 BDB 存储引擎,对自动提交的特性支持完成。

  • InnoDB被称为事务安全型引擎。

---事务开启 start transaction; 或者 begin ; 开启事务后,所有被执行的SQL语句均被认作当前事务内的SQL语句。 

-- 事务提交 commit; 

-- 事务回滚 rollback; 如果部分操作发生问题,映射到事务开启前

事务的特性

1.原子性(Atomicity)
      事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

2.一致性(Consistency)
      事务前后数据的完整性必须保持一致
      -事务开始和结束时,外部数据一致
      -在整个事务过程中,操作是连续的

3.隔离性(Isolation)
      多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间的数据要相互隔离。
      事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的

4.持久性(Durability)
      一个事务一旦被提交,它对数据库中的数据改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

--事务的实现

1. 要求是事务支持的表类型

2. 执行一组相关的操作前开启事务

3. 整组操作完成后,都成功,则提交;如果存在失败,选择回滚,则会回到事务开始的备份点。

--事务的原理

利用InnoDB的自动提交(autocommit)特性完成。
普通的MySQL执行语句后,当前的数据提交操作均可被其他客户端可见。
而事务是暂时关闭“自动提交”机制,需要commit提交持久化数据操作。

--注意

1. 数据定义语言(DDL)语句不能被回滚,比如创建或取消数据库的语句,和创建、取消或更改表或存储的子程序的语句。

2. 事务不能被嵌套

并发事务带来的几个问题

更新丢失,脏读,不可重复读,幻读。
事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)

--Read Uncommitted(读取未提交内容)
      在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

--Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

--Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

--Serializable(可串行化) 
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。



--ps:这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
--脏读(Drity Read):
某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

--不可重复读(Non-repeatable read):
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

--幻读(Phantom Read):
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

1,脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

4.可重复读(Repeatable read)是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。

悲观锁和乐观锁

--乐观锁
乐观锁不是数据库自带的,需要我们自己去实现,
乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,
在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,
再去判断是否有冲突了。

--悲观锁
每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,
这样别人想拿这个数据就会block(阻塞)直到它拿到锁

设计到锁的问题

更新丢失:最后的更新覆盖了其他事务之前的更新,而事务之间并不知道,发生更新丢失。更新丢失,可以完全避免,应用对访问的数据加锁即可。

脏读:(针对未提交的数据)一个事务在更新一条记录,未提交前,第二个事务读到了第一个事务更新后的记录,那么第二个事务就读到了脏数据,
会产生对第一个未提交,解决方案加锁,或者调整mysql事务隔离级别,数据库的事务隔离越严格,并发负作用越小,代价越高

MySQL主从同步原理

mysql主从同步的原理很简单,从库生成两个线程,一个I/O线程,一个SQL线程;i/o线程去请求主库 的binlog(二进制日志),
并将得到的binlog日志写到relay log(中继日志) 文件中;主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog;
SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致

关于binlog日志

binlog是二进制日志文件,用于记录mysql的数据更新或者潜在更新(比如DELETE语句执行删除而实际并没有符合条件的数据)

binlog索引文件mysql-bin.index。如官方文档中所写,binlog格式如下:

binlog文件以一个值为0Xfe62696e的魔数开头,这个魔数对应0xfe 'b''i''n'。

binlog由一系列的binlog event构成。每个binlog event包含header和data两部分。

header部分提供的是event的公共的类型信息,包括event的创建时间,服务器等等。

data部分提供的是针对该event的具体信息,如具体数据的修改。

主从同步延迟问题:

架构方面

1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。

2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。

3.服务的基础架构在业务和mysql之间加入memcache或者Redis的cache层。降低mysql的读压力。

4.不同业务的mysql物理上放在不同机器,分散压力。

5.使用比主库更好的硬件设备作为slave

总结,mysql压力小,延迟自然会变小。

硬件方面

1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。

2.存储用ssd或者盘阵或者san,提升随机写的性能。

3.主从间保证处在同一个交换机下面,并且是万兆环境。

总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。

mysql主从同步加速

1、sync_binlog在slave端设置为0

2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。

3、直接禁用slave端的binlog

4、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit = 2

MySQL优化

为什么要优化

系统的吞吐量瓶颈往往出现在数据库的访问速度上 随着应用程序的运行,数据库的中的数据会越来越多,
处理时间会相应变慢 数据是存放在磁盘上的,读写速度无法和内存相比

如何优化
设计数据库时:数据库表、字段的设计,存储引擎 利用好MySQL自身提供的功能,如索引等 横向扩展:MySQL集群、负载均衡、读写分离 SQL语句的优化(收效甚微)

原文地址:https://www.cnblogs.com/wonderlandlove/p/12877809.html