MySQL.存储引擎-事务-隔离级别-锁
Posted Steve--DZC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL.存储引擎-事务-隔离级别-锁相关的知识,希望对你有一定的参考价值。
mysql.存储引擎-事务-隔离级别-锁
1.什么是存储引擎?
? MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能
2.存储引擎有那些?这些引擎有那些特性?
2.1.Mylsam
MyIsam 存储引擎独立于操作系统,也就是可以在windows上使用,也可以比较简单的将数据转移到linux操作系统上去。这种存储引擎在创建表的时候,会创建三个文件,一个是.frm文件用于存储表的定义,一个是.MYD文件用于存储表的数据,另一个是.MYI文件,存储的是索引。操作系统对大文件的操作是比较慢的,这样将表分为三个文件,那么.MYD这个文件单独来存放数据自然可以优化数据库的查询等操作。
2.1.1.不支持事务,但是并不代表着有事务操作的项目不能用MyIsam存储引擎,可以在service层进行根据自己的业务需求进行相应的控制。
2.1.2.不支持外键。
2.1.3.查询速度很快。如果数据库insert和update的操作比较多的话采用表锁效率低(建议使用innodb
2.1.4.对表进行加锁。
2.2.Mrg_Mysam
Merge存储引擎,是一组MyIsam的组合,也就是说,他将MyIsam引擎的多个表聚合起来,但是他的内部没有数据,真正的数据依然是MyIsam引擎的表中,但是可以直接进行查询、删除更新等操作。
比如:我们可能会遇到这样的问题,同一种类的数据会根据数据的时间分为多个表,如果这时候进行查询的话,就会比较麻烦,Merge可以直接将多个表聚合成一个表统一查询,然后再删除Merge表(删除的是定义),原来的数据不会影响。
2.3.Memory
Memory采用的逻辑介质是内存,响应速度应该是很快的,但是当mysqld守护进程崩溃的时候数据会丢失,另外,要求存储的数据是数据长度不变的格式,比如,Blob和Text类型的数据不可用(长度不固定的)。
使用Memory存储引擎情况
2.4.Blackhole
“黑洞”存储引擎,他会丢弃所有的插入的数据,服务器会记录下Blackhole表的日志,所以可以用于复制数据到备份数据库。看其他的一些资料说:可以用来充当dummy master,利用blackHole充当一个“dummy master”来减轻master的负载,对于master来说“dummy master” 还是一个slave的角色,还有充当日志服务器等等。
2.5.CSV
可以将scv文件作为MySql的表来使用,但是不支持索引。CSV引擎表所有的字段都必须为非空的,创建的表有两个,分别是CSV文件和CSM文件。
2.6.Performance_Schema
MySQL5.5以后新增了一个存储引擎,就是Performance_Schema,他主要是用来收集数据库服务器的性能参数。MySQL用户不能创建存储该类型的表。
他提供了以下的功能1.提供进程等待的详细信息,包括锁、互斥变量、文件信息。
2.保存历史的事件汇总信息,为Mysql服务器的性能做出详细的判断。
3.对于新增和删除监控时间点都非常容易,并可以随意的改变Mysql服务器的监控周期
需要在配置文件my.cnf中进行配置才能开启。
2.7.Archive
archive是归档的意思,仅仅支持插入和查询两种功能,在MySQL5.5以后支持索引功能,他拥有很好的压缩机制,使用zlib压缩库,在记录请求的时候实时的进行压缩,经常被用来作为仓库使用。适合存储大量的独立的作为历史记录的数据。拥有很高的插入速度但是对查询的支持较差。
2.8.Federated
Federated存储引擎是访问MySQL服务器的一个代理,尽管该引擎看起来提供了一个很好的跨服务器的灵活性,但是经常带来问题,默认是禁用的。
2.9.InnoDB
InnoDB是一个事务型的存储引擎,有行级锁定和外键约束,适用于以下的场合:
- 更新多的表,适合处理多重并发的更新请求。
- 支持事务。
- 可以从灾难中恢复(通过bin-log日志等)。
- 外键约束。只有他支持外键。
- 支持自动增加列属性auto_increment。
如何修改数据库默认存储引擎:
方式一:
修改配置文件my.ini,在linux中为my.conf文件
在[mysqld]后面添加default-storage-engine=InnoDB,重启服务,数据库默认的引擎修改为InnoDB
方式二:
在建表的时候指定
create table test( )engine=‘MyISAM‘;
方式三:
建表后更改
‘‘‘MySql alter table table_name engine = ‘InnoDB‘; 数据量很大的情况下可能要等一段时间
怎么查看修改成功?
方式一:
show table status from database_name;
方式二:
show create table table_name;
3.常用的三种数据引擎的比较
RDBMS(OLTP)关系数据库管理系统(Relational Database Management System)
4.1.ISAM:ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。ISAM的两个主要不足之处在于,它不支持事务处理,也不能够容错:如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把ISAM用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,MYSQL能够支持这样的备份应用程序。
MyISAM:MyISAM是MySQL的ISAM扩展格式和缺省的数据库引擎。除了提供ISAM里所没有的索引和字段管理的大量功能,MyISAM还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行OPTIMIZE
TABLE命令,来恢复被更新机制所浪费的空间。MyISAM还有一些有用的扩展,例如用来修复数据库文件的MyISAMCHK工具和用来恢复浪费空间的
MyISAMPACK工具。MYISAM强调了快速读取操作,这可能就是为什么MySQL受到了WEB开发如此青睐的主要原因:在WEB开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和INTERNET平台提供商只允许使用MYISAM格式。MyISAM格式的一个重要缺陷就是不能在表损坏后恢复数据。
InnoDB:
InnoDB数据库引擎都是造就MySQL灵活性的技术的直接产品,这项技术就是MYSQL+API。在使用MYSQL的时候,你所面对的每一个挑战几乎都源于ISAM和MyISAM数据库引擎不支持事务处理(transaction
process)也不支持外来键。尽管要比ISAM和 MyISAM引擎慢很多,但是InnoDB包括了对事务处理和外来键的支持,这两点都是前两个引擎所没有的。如前所述,如果你的设计需要这些特性中的一者或者两者,那你就要被迫使用后两个引擎中的一个了。
MEMORY:MEMORY是MySQL中一类特殊的存储引擎。它使用存储在内存中的内容来创建表,而且数据全部放在内存中。这些特性与前面的两个很不同。每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同,类型为frm类型。该文件中只存储表的结构。而其数据文件,都是存储在内存中,这样有利于数据的快速处理,提高整个表的效率。值得注意的是,服务器需要有足够的内存来维持MEMORY存储引擎的表的使用。如果不需要了,可以释放内存,甚至删除不需要的表。MEMORY默认使用哈希索引。速度比使用B型树索引快。当然如果你想用B型树索引,可以在创建索引时指定。注意,MEMORY用到的很少,因为它是把数据存到内存中,如果内存出现异常就会影响数据。如果重启或者关机,所有数据都会消失。因此,基于MEMORY的表的生命周期很短,一般是一次性的。
在实际工作中,选择一个合适的存储引擎是一个比较复杂的问题。每种存储引擎都有自己的优缺点,不能笼统地说谁比谁好。
InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。
MyISAM: 插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。
MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。
注意,同一个数据库也可以使用多种存储引擎的表。如果一个表要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎。
4.事务
4.1.MySQL事务主要用于处理操作量大,复杂度高的数据
1).在MySQL中只有使用了Innodb数据库引擎的数据库和表才支持事务。
2)事物处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行。
3)事务用来管理insert,update,delete语句。
4.2.事务(ACID)
1)原子性(Atomicity不可分割性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
2)一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
3)隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
4)持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
4.4.事务控制语句:
BEGIN或START TRANSACTION:显示地开启一个事务:
COMMIT:也可以使用COMMIT WORK,不过二者是等价的。COMMIT提交事务,并使已对数据库进行的所有修改成为永久性的;
ROLLBACK:有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改:
SAVEPOINT identifier:SAVE[POMT 允许在事务中创建一个保存点。一个事务中可以有多个SAVE[POMT;
RELEASE SAVEPOIN identifier: 删除一个事务的保存点,一个事务中可以有多个SAVEPOINT;
ROLLEASE SAVEPOINT identifier:把事务回滚到标记点;
SET TRANSACTION :用来设置事务的隔离基本。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ和SERIALIZABLE.
4.3.MySQL事务处理主要有两种方法:
4.3.1.用BEGIN,ROLLBACK,COMMIT来实现
BEGIN开始一个事务
ROLLBACK事务回滚
COMMIT事务确认
4.3.2.直接用SET 来改变MySQL的自动提交模式;
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交事务测试
> mysql> use RUNOOB;
> Database changed
> mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb; # 创建数据表
> Query OK, 0 rows affected (0.04 sec)
>
> mysql> select * from runoob_transaction_test;
> Empty set (0.01 sec)
>
> mysql> begin; # 开始事务
> Query OK, 0 rows affected (0.00 sec)
>
> mysql> insert into runoob_transaction_test value(5);
> Query OK, 1 rows affected (0.01 sec)
>
> mysql> insert into runoob_transaction_test value(6);
> Query OK, 1 rows affected (0.00 sec)
>
> mysql> commit; # 提交事务
> Query OK, 0 rows affected (0.01 sec)
>
> mysql> select * from runoob_transaction_test;
> +------+
> | id |
> +------+
> | 5 |
> | 6 |
> +------+
> 2 rows in set (0.01 sec)
>
> mysql> begin; # 开始事务
> Query OK, 0 rows affected (0.00 sec)
>
> mysql> insert into runoob_transaction_test values(7);
> Query OK, 1 rows affected (0.00 sec)
>
> mysql> rollback; # 回滚
> Query OK, 0 rows affected (0.00 sec)
>
> mysql> select * from runoob_transaction_test; # 因为回滚所以数据没有插入
> +------+
> | id |
> +------+
> | 5 |
> | 6 |
> +------+
> 2 rows in set (0.01 sec)
>
> mysql>
5.RDBMS关系数据库管理(Relational Database Managemet System)
5.1.事务的隔离级别
1)Read Uncommitted(读取未提交内容)
2) Read Committed(读取提交内容)
3)Repeatable Read(可重读)
4) Serializable(可串行化)
Scala有8种数据类型:Byte,Char,Short,Int,Long,Float,Double以及Boolean
隔离级别 脏读 不可重复读 幻读 读未提交(Read uncommitted) true true true 读已提交(Read committed) false true true 可重复读(Repeatable read) false false true 可串行化(Serializable) false false false
5.2.事务并发执行的现象
1)第一类丢是更新:在没有事务隔离的情况下,两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。
例如:
张三的工资为5000,事务A中获取工资为5000,事务B获取工资为5000,汇入100,并提交数据库,工资变5100, 随后事务A发生异常,回滚了,恢复张三的工资为5000,这样就导致事务B的更新丢失了。
2)脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种还没有提交到数据库种,这是,另外一个事务也访问这个数据,然后使用了这个数据。
张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。 与此同时, 事务B正在读取张三的工资,读取到张三的工资为8000。 随后, 事务A发生异常,而回滚了事务。张三的工资又回滚为5000。 最后, 事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
3)不可重复读:是指在一个事务内,多次读同一个数据。在这个事务还没有结束时,另外一个事务也访问该同一个数据。那么,在第一个事务种的两此读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
例如: 在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。 与此同时, 事务B把张三的工资改为8000,并提交了事务。 随后, 在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
4)第二类丢失更新:不可重复读的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一此写操作失效。
例如: 在事务A中,读取到张三的存款为5000,操作没有完成,事务还没提交。 与此同时, 事务B,存储1000,把张三的存款改为6000,并提交了事务。 随后, 在事务A中,存储500,把张三的存款改为5500,并提交了事务,这样事务A的更新覆盖了事务B的更新。
5)幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
例如: 目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。 此时, 事务B插入一条工资也为5000的记录。 这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。
提醒:
不可重复读的重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样了
幻读的种的在于新曾或者删除,同样的条件,第1次和第2次读出来的记录数不一样
6 .0.锁
MySQL各种存储引擎使用了三种类型(级别)的锁定制机制:
1.表级锁定(table-level):表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。
注意:当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。
2.行级锁定(row-level):行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。使用行级锁定的主要是InnoDB存储引擎。
3.页级锁定(page-level):页级锁定是MySQL中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。
在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
使用页级锁定的主要是BerkeleyDB存储引擎。
共享锁(S) 排他锁(X) 意向共享锁(IS) 意向排他锁(IX) 共享锁(S) 兼容 冲突 兼容 冲突 排他锁(X) 冲突 冲突 冲突 冲突 意向共享锁(IS) 兼容 冲突 兼容 兼容 意向排他锁(IX) 冲突 冲突 兼容 兼容 总结:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
在数据库引擎InnoDB中支持行锁和表锁用的也比较多,但是Myisam不支持事务,只支持表锁
[隔离级别]
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同的数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须取得该表的IX锁
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取的该表的IS锁
以上是关于MySQL.存储引擎-事务-隔离级别-锁的主要内容,如果未能解决你的问题,请参考以下文章