-
MySQL基础架构
-
连接管理器:接收请求接收请求
-->
创建线程-->
认证用户-->
建立安全连接; -
优化器的缺陷:
- 有时候执行的优化并不一定是最优化的,如果有最优化的方式,直接进行指定,不建议进行优化,省去优化器优化的开销;
- 优化器优化的过程并不会考虑存储引擎的不同;
-
不是所有的结果都是需要进行缓存的,非确定性结果就不应该进行缓存,具有实时性要求的,不应该进行缓存;
-
并发控制的一种原理,每个用户操作访问的都不是源数据,而是数据的快照,最后完成快照恢复,这种机制成为
MVCC
,也就是多版本并发访问控制机制, -
不能够缓存的例如当前时间,这种结果是非确定性结果;
-
对于多版本并发控制依赖的手段:
- 锁机制:一个事务可能在启动事务时,长时间得不到锁,出现饥饿现象;还有可能出现死锁状况,如果出现死锁,事务调度,就应该控制事务进行回退;
- 时间戳;
- 多版本和快照隔离
-
简单的锁控制机制:
- 锁是最简单的并发机制控制;
- 读锁是共享锁;
- 写锁是独占锁;
-
表锁:锁定一张表;
-
页锁:锁定数据页面,数据页面可能包含多个行;
-
行锁:锁定某一个行;
-
MySQL
服务器仅仅支持表级别的锁,行锁需要由存储引擎完成,存储引擎都有自己的锁策略,很少需要手动的在服务器上面施加锁; -
LOCK_TABLE
-
手动施加读锁
mysql> LOCK TABLES tutors read;
Query OK, 0 rows affected (0.00 sec)
- 在另一个会话中开始进行查询,数据查询是允许的;
mysql> SELECT * FROM tutors;
+-----+--------------+--------+------+
| TID | Tname | Gender | Age |
+-----+--------------+--------+------+
| 1 | HongQigong | M | 93 |
| 2 | HuangYaoshi | M | 63 |
| 3 | Miejueshitai | F | 72 |
| 4 | OuYangfeng | M | 76 |
| 5 | YiDeng | M | 90 |
| 6 | YuCanghai | M | 56 |
| 7 | Jinlunfawang | M | 67 |
| 8 | HuYidao | M | 42 |
| 9 | NingZhongze | F | 49 |
| 10 | DingDian | M | 25 |
| 11 | HuFei | M | 31 |
| 12 | ZhangWuji | M | 20 |
| 13 | Xuzhu | M | 26 |
| 14 | LingHuchong | M | 22 |
+-----+--------------+--------+------+
14 rows in set (0.00 sec)
- 插入数据是不能够完成的,陷入等待释放读锁
- 释放读锁,数据插入立即完成
-
事务的特性
-
需要满足
ACID
特性,也就是满足- 原子性:
Automicity
事务涉及的多个执行语句,要么同时完成,要么同时不完成,必须当作一个整体来看待; - 一致性:
Consistency
:一致性,事务执行结束之后,数据库的执行状态是没有改变的; - 隔离性:
Isolation
:隔离性,用于保证各个事务之间彼此不被影响,通过各个之间的事务调度执行,各个事务之间降低彼此之间的影响; - 持久性:
Durability
持久性,一旦事务成功完成,都必须保证这个事务是稳定的,系统出现必须保证任何故障下都不会引起事务表示出不一致性;- 1.事务提交之前的数据应该写入永久性存储,效率低下;
- 2.结合事务日志,事务日志是保存在永久性存储设备上面的;
- 3.事务日志产生的是顺序
IO
,在存储的时候是连续的,数据文件是随机IO
;
- 原子性:
-
MySQL
的事务引擎是交给存储引擎来控制的,InnoDB
是支持事务的; -
事务日志:
-
重做日志
Redo
:表示按照日志里面记录的信息,将需要的重新完成一遍; -
撤销日志
undo log
: 表示撤销日志纪录中已经完成的操作; -
为了结合事务日志的处理机制,
MySQL
的数据处理都是在内存中完成,并且将操作的记录写在事务日志中,然后将事务日志按照里面的记录在磁盘上面对数据进行操作; -
对于数据的增删查改,首先在内存中完成,然后写入事务日志中,通过事务日志的重做日志在执行一遍,然后写入实际的数据文件中去,写在日志中,要快的多,日志中记录的仅仅是操作,而不是数据文件本身;
- 对于完成提交的事务,如果在写入磁盘的过程中崩溃,那么需要重做日志进行重做;
- 对于没有完成的事务,再写入次怕的过程中崩溃,那么执行撤销日志,撤销执行;
- 日志文件应该尽量小,但是应该存在不止一个,通常使用是日志组来完成的;
-
事务日志文件通常不是一个,而是多个,称为日志组,一个用于进行写入,另一个马上在磁盘上面的重做操作,通常是交替进行;
-
事务日志和数据文件应该在不同的设备上面;
-
事务的状态
-
ACTIVE
:活动的; -
部分提交:最后一条语句正在执行;
-
失败的:事务正常提交,但是提交没有完成;
-
终止的:没有提交,就提前结束的;
-
提交的:成功提交,并且成功执行的,事务一旦提交,就没有办法撤销,如果需要撤销,就只能够通过补偿事务来完成;
-
事务允许进行并发执行,并且通过调度来保证事务的特性:
-
可恢复调度:任何两个事务的交叉执行,都不会导致另外一个事务状态的改变,会滚的时候可能存在影响;
-
无级联调度: 为了避免事务在会滚的时候产生影响;
-
事务的隔离级别
-
这是在启动两个事务的情况下,根据不同的隔离级别,出现不同的结果;
-
隔离级别越低,事务存在干扰的可能性越大
-
read uncommitted
:读未提交, 别人操作,可以立即看见,隔离级别最低; -
read commited
:读提交,表示别人提交之后,可以立即看到,会出现幻读; -
repeatabled read
:表示可重读,表示无论是否进行提交,从第一次看到直到事务提交之前都是什么样;MySQL
默认是这样的; -
serialiable
:表示按照串行进行执行; -
隔离级别越高,并发能力越低,降低隔离级别可以提高
MySQL
性能; -
查看默认的隔离级别
mysql> SHOW GLOBAL VARIABLES LIKE '%iso%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
- 事务的隔离级别
mysql> SET tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)
- 事务的操作
- 启动一个事务
mysql> START TRANSACTION;
- 执行
SQL
语句 - 然后进行提交事务,
mysql> commit;
- 执行
commit
之后,事务就不能够撤销的; - 在执行
SQL
语句的时候,如果放弃事务的执行,可以使用ROLLBACK
来放弃事务的执行; - 启动一个事务
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM tutors;
+-----+--------------+--------+------+
| TID | Tname | Gender | Age |
+-----+--------------+--------+------+
| 1 | HongQigong | M | 93 |
| 2 | HuangYaoshi | M | 63 |
| 3 | Miejueshitai | F | 72 |
| 4 | OuYangfeng | M | 76 |
| 5 | YiDeng | M | 90 |
| 6 | YuCanghai | M | 56 |
| 7 | Jinlunfawang | M | 67 |
| 8 | HuYidao | M | 42 |
| 9 | NingZhongze | F | 49 |
| 10 | DingDian | M | 25 |
| 11 | HuFei | M | 31 |
| 12 | ZhangWuji | M | 20 |
| 13 | Xuzhu | M | 26 |
| 14 | LingHuchong | M | 22 |
| 15 | jerry | M | 50 |
+-----+--------------+--------+------+
15 rows in set (0.00 sec)
- 接下来执行一些操作
mysql> DELETE FROM tutors WHERE Tname LIKE 'je%';
Query OK, 0 rows affected (0.00 sec)
- 查看数据,已经被删除,但是没有同步到磁盘上面;
- 如果不想进行删除,不要进行
commit
而是进行ROLLBACK
进行事务的回滚操作
mysql> ROLLBACK;
Query OK, 0 rows affected (0.00 sec)
auto_commit
:表示事务的自动提交
mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
- 如果没有明确的启动事务,就能够实现自动提交的,不能够执行
ROLLBACK
的,建议明确使用事务,并且关闭自动提交,否则IO
导致性能降低; - 关闭这个变量之后,就可以进行回滚操作了,但是对于确定的操作,需要执行
commit
操作
mysql> SET autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM tutors WHERE Tname='jerry';
Query OK, 1 row affected (0.00 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)
- 事务的SAVEPOINT:
- 在进行事务里面的大量语句操作时,设置保存点,在进行语句撤销时,一次撤销到某个保存点,而不是撤销完成所有的语句;
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM tutors WHERE TID=10;
Query OK, 1 row affected (0.00 sec)
mysql> SAVEPOINT ab;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM tutors WHERE TID=9;
Query OK, 1 row affected (0.00 sec)
mysql> SAVEPOINT ac;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM tutors WHERE TID=8;
Query OK, 1 row affected (0.00 sec)
mysql> SAVEPOINT ad;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM tutors WHERE TID=7;
Query OK, 1 row affected (0.00 sec)
mysql> SAVEPOINT ae;
Query OK, 0 rows affected (0.00 sec)
- 执行完上述操作之后
- 然后进行回滚到某个
SAVEPOINT
;
- 事务的隔离级别对于事务的影响
- 启动两个
MySQL
会话,并且设定默认的隔离级别为下面的几种: - 验证
READ_UNCOMMITTED
: - 会话
1
:
mysql> SET tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
- 会话
2
:
mysql> SET tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
- 交叉启动事务
- 会话
1
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)
- 会话
2
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 修改某个用户的年龄
- 在会话
1
里面修改HuFei
的年龄
mysql> UPDATE tutors SET Age=50 WHERE TID=12;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
- 然后再会话
2
里面进行查看,是可以查看到修改的内容的
- 如果会话
1
执行了,撤销操作
mysql> ROLLBACK;
Query OK, 0 rows affected (0.03 sec)
- 那么会话
2
就会就会修为原来的数据
- 接下来修改级别为
READ-COMMITTED
; - 会话
1
mysql> SET tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 会话
2
:
mysql> SET tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 接下来修改数据
- 会话
1
mysql> UPDATE tutors SET Age=50 WHERE TID=12;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
- 会话
2
查看数据,TID
为12
的并没有进行修改
- 会话
1
在进行提交之后,这个值就会发生改变
mysql> COMMIT;
Query OK, 0 rows affected (0.25 sec)
- 会话
2
查看的数据已经发生改变
- 提交事务
- 会话
1
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec
- 会话
2
,进行提交
mysql> COMMIT;
Query OK, 0 rows affected (0.25 sec)
- 修改事务隔离级别为
REPEATABLE-READ
,并且启动事务 - 会话
1
mysql> SET tx_isolation='REPEATABLE-READ';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.01 sec)
- 会话
2
,同时修改事务隔离级别,并且启动事务
mysql> SET tx_isolation='REPEATABLE-READ';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 接下来进行数据的修改
- 会话
1
mysql> UPDATE tutors SET Age=100 WHERE TID=12;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
- 会话
2
,查看数据是否发生改变
- 会话
1
提交事务,会话2
上面查询的数据仍然没有改变
mysql> COMMIT;
Query OK, 0 rows affected (0.79 sec)
-
会话
2
上面的数据,没有发生改变;
-
会话
2
进行事务的提交,查看数据,已经进行更新
-
验证SERIALIZALE
-
会话
1
修改,日志的隔离级别为SERIALIZABLE
,并且启动事务
mysql> SET tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 会话
2
同样进行修改,并且启动日志
mysql> SET tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
- 在会话
1
上面进行修改数据
mysql> UPDATE tutors SET Age=10 WHERE TID=12;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
- 会话
2
上面是查询不到变化的信息的,因为不允许两个事务同时操作同一个数据
mysql> SELECT * FROM tutors;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
- 在会话
1
上面提交数据
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
- 会话
1
的数据修改完成
- 会话
2
的查看就可以正常完成,并且可以得到信息
- 会话
2
提交数据之后,得到信息是不会发生改变的