手记

MySQL杂谈

应用场景

这个可能要依据所采用的存储引擎(myisam,innerdb)来看。

读写分离

在Django框架下,数据库的读写分离的设计一般有两种方式:

  1. 手动实现
    获取queryset的时候调用using

transaction = PrepayTransactions.objects.using('read').filter(channel='wechat', deactivated_at__is_null=True).first()
transaction.channel = 'alipy'transaction.save(using='read')
  1. 自动处理
    重写数据库路由,然后在settings文件里添加上该路由的具体path

class MasterSlaveDBRouter(object):
    """数据库主从读写分离路由"""

    def db_for_read(self, model, **hints):
        """读数据库"""
        return "slave"

    def db_for_write(self, model, **hints):
        """写数据库"""
        return "default"

    def allow_relation(self, obj1, obj2, **hints):
        """是否运行关联操作"""
        return True

然后配置读写分离(settings.py)
DATABASE_ROUTERS = [‘path_to_router.MasterSlaveDBRouter’]

主从复制

这个一般是从MySQL的高可用性来说的,都是基于MySQL Replication来实现的,模式主要有四种:

  1. 一主一从

  2. 一主多从

  3. 主主互备

  4. 双主多从

其中读业务数据量特别大的时候考虑多从架构,另外为了实现一台master出现故障时自动切换,可以采用keepalived(主主互备架构,只会监控到主节点的状态)、MMM(双主多从比较好,同时监控master和slave节点的状态)等工具来实现。

乐观锁和悲观锁

  1. 乐观锁
    乐观的认为在自己取数据的时候不会有其他线程来更改数据,因此取数据的时候不加锁,但对数据进行update等写的操作时要加锁(这个一般通过版本号设计,CAS设计来实现)

  2. 悲观锁
    不管是读数据还是更新数据都加上锁,这个一般在数据库级别来实现,比如mysql自己的锁机制(行锁,表锁,读锁,写锁)

选择问题:这个要依据实际的应用场景来决定,一般来讲,读频繁的数据库加乐观锁,而写频繁的数据库加悲观锁。

事务及事务的隔离级别

事务的四大特性

ACID:
原子性,一致性,隔离性,持久性

事物的隔离级别

  1. 读未提交 — 脏读

  2. 读提交 —  不可重复读

  3. 可重复读  — 幻读

  4. 串行化  — 事务隔离的最高级别
    可序列化的数据库锁情况:
    事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放 — 其他事务通过添加共享锁也可以读取数据
    事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放 — 其他事务不能对其进行读写操作

另外,补充几个概念:
脏读:事务A修改了某个数据但未提交,然后事务B读了这条数据(更改后),后来事务A回滚了,这就形成事务B的脏读;
不可重复读:事务A先读了某个数据,而事务B对这个数据进行了更改且提交了,这时候事务A再读这个数据时发现跟之前读的数据不一样了,这就是不可重复读;
幻读:其实跟不可重复读有点类似,只不过幻读侧重新增数据,而不可重复读则侧重更新或者删除;



作者:VienFu
链接:https://www.jianshu.com/p/2bad560976f3


0人推荐
随时随地看视频
慕课网APP