MySQL事务及隔离级别详解
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.MySQL的基本架构
MySQL的基本架构可以分为三块,即连接池,核心功能层,存储引擎层。
1>.连接池 (线程处理工具)
主要功能是与用户请求建立连接。第一层向用户响应请求的数据,这个层次不是MySQL服务独有的,其实大多数C/S架构的工作软件基本上都是这种工作模式,只不过在处理连接池的内存,进程的释放等管理关系上mysql可能有着自己独特的方式。
我们知道MySQL是单进程多线程的模型,MySQL的线程有很多种类型,比方说:负责和用户建立连接的叫做连接线程,把缓存中的数据同步到磁盘中去的叫做刷新线程,甚至于不同的存储引擎还维持着多个后台线程等等。那么一个MySQL服务器和客户端同时能建立多少个连接呢?mysql管理连接是通过线程池来实现的,其实很多基于线程机制的连接管理器都基于线程池(thread pool)来管理的。一个线程池所拥有的线程数是有限的,所以我们MySQL在启动的时候会事先创建一个线程池,比如在创建了100个线程,那么来一个客户端连接就给它分配一个线程,当连接的总数到达150(超过提前创建的100个线程数量了)时,MySQL会先响应前100个线程,而将后面的50个请求放在一个队列中,然他们在这个队列中进行排队,一旦前面的100个线程中的任意一个用户退出了,就会空出来一个线程,这个空出来的线程不会被销毁,而是把这个线程给它清理一下,还原到最初的样子,再去响应在队列中排队的50个线程的任何一个。所以用户的连接线程在线程池的管理模式中是不会被销毁的,一般会实现线程重用,从而避免了线程的重建和释放。
MySQL的客户端和服务器进行连接是基于msyql协议的,MySQL支持文本协议和二进制的协议。只不过二进制的协议高效一些。不管是基于文本还是二进制协议mysql的发送数据默认为明文(也就是我们用一个解码器就可以将数据直接读取出来,尽管你用了二进制编码或是其他文本格式编码),可以使用ssl加密数据。
2>.核心功能层
主要功能是查询解析,分析,优化,缓存,内置函数(BIF),触发器,视图等跨存储引擎的功能,你也可以说MySQL的主要功能都在这一层提供。第二次我们也可以叫它为MySQL的核心服务层。
3>.存储引擎层
主要功能是对数据的存入和提取。我们知道MySQL是插件式存储引擎,而存储引擎又是表级别的概念,我们创建任何一张表的时候我们都可以指定它的存储引擎,在同一个库中的多个表可以使用不同的存储引擎,所以我们说存储引擎对MySQL来讲是一个非常灵活的机制。
二.MySQL锁
MySQL的并发访问控制是基于锁来实现。
1>.执行操作时施加的锁的模式有以下两种:
读锁:
特点是用户在读的时候施加的锁,为防止别人修改,但是用户可以读,即可以多个用户可以同时对一张表进行读取操作但不能修改数据该表的内容,因此读锁还被称为共享锁。在做数据备份时要建议手动施加读锁。
写锁:
特点是当对一个表做修改操作时,其他用户不能对这张表进行读同时也不能写哟。因此写锁也被称为独占锁或排它锁。
2>.施加的锁的粒度(简称锁粒度)有以下两种:
表锁(table lock):
锁定了整张表。 表锁是关系型数据库中最基本的锁策略,也是开销最小的锁策略(因为请求锁,施加锁,释放锁,管理锁都是急需要占用资源的)。
行锁(row lock):
只锁定了表中需要的行,不一定是一行哟。
表锁有个缺点,就是当用户对一张表进行修改操作时会锁定整张表,如果表中的数据有1万行,而当前用户只是需要修改其中的几行内容,这会导致其他用户想要查询前用户不需要修改的行是被拒绝,需要等待该用户操作完成结束方能进行查询操作。因此我们总结为:“ 粒度越小,开销越大,但并发性越好, 粒度越大,开销越小,但并非性越差。”在实际生产环境中,数据库的锁策略至关重要。
3>. 根据锁的实现位置分为以下两种:
1 MySQL锁:可以手动使用,可以使用显示锁 2 存储引擎锁:自动进行的(隐式锁), 3 a>.显示锁: 4 lock tables:施加锁 5 LOCK TABLES:解锁 6 tbl_name lock_type 7 [, tbl_name lock_type] ... 8 READ | WRITE 锁的类型 9 unlock tables:解锁 10 b>.InnoDB存储引擎也支持另外一种显示锁(锁定挑选出的部分行,行级锁) 11 select .... lock in share mode 12 select .... for update
1 mysql> select database(); 2 +-------------+ 3 | database() | 4 +-------------+ 5 | yinzhengjie | 6 +-------------+ 7 1 row in set (0.00 sec) 8 9 mysql> 10 mysql> show tables; 11 +-----------------------+ 12 | Tables_in_yinzhengjie | 13 +-----------------------+ 14 | Classes | 15 | score | 16 | students | 17 | tearchers | 18 +-----------------------+ 19 4 rows in set (0.00 sec) 20 21 mysql> 22 mysql> 23 mysql> 24 mysql> desc Classes; 25 +-------------+-------------+------+-----+---------+-------+ 26 | Field | Type | Null | Key | Default | Extra | 27 +-------------+-------------+------+-----+---------+-------+ 28 | ClassID | tinyint(4) | NO | | NULL | | 29 | Class | varchar(50) | NO | | NULL | | 30 | ClassMember | tinyint(4) | NO | | NULL | | 31 +-------------+-------------+------+-----+---------+-------+ 32 3 rows in set (0.00 sec) 33 34 mysql> 35 mysql> lock tables Classes read; #将Classes 设置读锁 36 Query OK, 0 rows affected (0.00 sec) 37 38 mysql> select * from Classes; #发现即使配置给Classes表配置了读锁,当是我们可以进行读取操作。 39 +---------+--------------------------+-------------+ 40 | ClassID | Class | ClassMember | 41 +---------+--------------------------+-------------+ 42 | 7 | 木叶忍者村第七班 | 4 | 43 | 10 | 木叶忍者村第十班 | 3 | 44 | 8 | 木叶忍者村第八班 | 3 | 45 | 3 | 木叶忍者村第三班 | 3 | 46 +---------+--------------------------+-------------+ 47 4 rows in set (0.01 sec) 48 49 mysql> 50 mysql> insert into Classes value (1,'木叶忍者村第一班',5); #事假读锁之后发现无法向Classes表中插入数据 51 ERROR 1099 (HY000): Table 'Classes' was locked with a READ lock and can't be updated 52 mysql> 53 mysql> unlock tables; #现在我们进行一下解锁 54 Query OK, 0 rows affected (0.00 sec) 55 56 mysql> insert into Classes value (1,'木叶忍者村第一班',5); #解锁成功后,我们就可以可以插入数据啦。 57 Query OK, 1 row affected (0.03 sec) 58 59 mysql>