MySQL存储引擎:MyISAM & InnoDB

存储引擎

现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用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()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值