您的位置:首页 > 数据库 > MySQL

MySQL存储引擎:MyISAM & InnoDB

2017-12-25 16:59 375 查看

存储引擎

现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存表格用excel,存图片用png等。数据库中的表也应该有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎。

存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)

在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySQL数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。

MySQL最常用的两个引擎:MyISAM 和 InnoDB 这里说一下二者的主要特性和区别。

MyISAM 支持全文索引,不支持事务、也不支持外键,所以访问速度较快。因此当对事务完整性没有要求并以访问(SELECT, INSERT)为主的应用适合使用该存储引擎

InnoDB 在支持事物,即支持具有提交、回滚及崩溃恢复能力等事务特性,所以比MyISAM存储引擎占用更多的磁盘空间,写的效率也差一些。因此当需要频繁的更新、删除操作,同时还对事务的完整性要求较高(类似计费系统或者财务系统等对数据准确性要求比较高的系统),需要实现并发控制,建议选择。

另外,二者对锁的支持也有不同,MyISAM 支持表锁,而InnoDB 支持行锁和表锁。

要对某个数据执行操作,在此期间不希望其它请求修改该数据时,就可以加锁。

MyISAM 表锁

MyISAM 表锁有两种:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。

表共享读锁:不会阻塞其它用户对同一表的读请求,但会阻塞对同一表的写请求。

表独占写锁:阻塞其它用户对同一表的读和写操作。

加锁和解锁:

-- 加读锁
LOCK TABLE tablename READ
-- 加写锁
LOCK TABLE tablename WRITE

-- 对数据库数据执行操作
-- SELECT ...

-- 解锁
UNLOCK TABLES


MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。MyISAM表的读操作与写操作之间,以及写操作与写操作之间是串行的!

InnoDB 行锁和表锁

行锁

InnoDB 实现了以下两种类型的行锁:

共享锁:其它事物仍然可以查询,并获得共享锁,但是不能UPDATE 或者 DELETE 操作。一旦获得共享锁的当前事物需要对共享锁记录进行更新操作,而另一个事物也有共享锁时,需要等待锁,直到另一个事务死锁退出而获得锁。

排他锁:允许获得排他锁的事务更新数据,其它事物可以查询记录,但是不能加共享锁更不能更新数据据,要等待锁。

对于 UPDATE、 DELETE 和 INSERT 语句, InnoDB会自动给涉及数据集加排他锁;对于普通 SELECT 语句,InnoDB 不会加任何锁;

显示地给记录集加共享锁或排他锁。

SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 -- 共享锁
SELECT * FROM table_name WHERE ... FOR UPDATE。 -- 排它锁


行锁实现方式及注意事项

InnoDB 行锁是通过给索引上的索引项加锁来实现的,这一点 MySQL 与 Oracle 不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB 这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB 才使用行级锁,否则,InnoDB 将使用表锁!

以下情形(id是主键索引)将会使用表锁:

根据索引未找到数据

SELECT * FROM table WHERE id=xx FOR UPDATE


根据索引找到的数不明确

SELECT * FROM table WHERE id>xx FOR UPDATE


根据非索引查找

SELECT * FROM table WHERE name = xx FOR UPDATE


在Django ORM中加锁

需要通过事务来实现:

from django.db import transaction  # 导入事务
with transaction.atomic():
res = models.UserInfo.objects.filter(id=1).select_for_update()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 数据库