事务、并发、锁机制的实现

配置全局事务

复制代码
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'USER':'root',
        'PASSWORD':'pass',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'ATOMIC_REQUESTS': True,  # 全局开启事务,绑定的是http请求响应整个过程
        # (non_atomic_requests可局部实现不让事务控制)
    }
}

配置全局事务中局部不受事务控制

复制代码
# 1.不受全局事务控制
# 如有多个数据库,让使用db的视图不受事务控制
@transaction.non_atomic_requests(using='db')
def my_other_view(request):
    pass

回滚点配置保存及提交

复制代码
sid = transaction.savepoint()  # 回滚点
with transaction.atomic():
    try:
        pass
    except Exception as e:
        # 如发生异常,回滚到指定地方。
        transaction.savepoint_rollback(sid)
    # 如果没有异常,显式地提交一次事务
    transaction.savepoint_commit(sid)

悲观锁的实现

复制代码
# django实现悲观锁
@transaction.atomic
def post(self, request):
    # select_for_update表示锁,只有获取到锁才会执行查询,否则阻塞等待。
    xxx.objects.select_for_update().get(id=1)
    # 等事务提交后,会自动释放锁。


# 同时使用select_for_update与select_related
# 只会锁定entry(self)和category,不会锁定作者author
xxx.objects.select_related('author', 'category').select_for_update(of=('self', 'category'))
# 注意:MySQL版本要在8.0.1 以上才支持 nowait,skip_locked和of选项。

乐观锁的实现

复制代码
# 乐观锁实现
@transaction.atomic
def post(self, request):
    goods_id = request.GET.get('id')
    count = int(request.GET.get('count'))
    while True:
        # 查询商品对象 -- 最基本查询
        goods = xxx.objects.filter(id=goods_id).first()
        origin_stock = goods.stock  # 获取原始库存,会检查是否有变化,乐观锁的特点
        sleep(5)
        # 减少商品的库存数量,保存到数据库
        xxx.objects.filter(id=goods_id, stock=origin_stock).update(stock=origin_stock - count)

mysql 的主从搭建的原因:

1.实现读写分离,多个msyql可实现提高并发量

2.主库写数据,从库读数据

docker ``pull mysql:5.7

创建文件夹,配置mysql1主,mysql2从数据库

mkdir /root/mysql1

mkdir /root/mysql1/conf.d

mkdir /root/mysql2/data/

touch /root/mysql2/my.cnf

mkdir /root/mysql2

mkdir /root/mysql2/conf.d

mkdir /root/mysql2/data/

touch /root/mysql2/my.cnf

配置主从数据库

主:/root/mysql1/my.cnf

复制代码
主
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
server-id=100                   # id
log-bin=mysql-bin               # bin
[client]
default-character-set=utf8
 
[mysql]
default-character-set=utf8

从:/root/mysql2/my.cnf

复制代码
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
server-id=101                  # id
log-bin=mysql-slave-bin         # bin
relay_log=edu-mysql-relay-bin 
 
[client]
default-character-set=utf8
 
[mysql]
default-character-set=utf8

启动mysql,设置端口和目录的映射

主库容器设置

docker run -di -v /root/mysql1/data/:/var/lib/mysql -v /root/mysql1/conf.d:/etc/mysql/conf.d -v /root/mysql1/my.cnf:/etc/mysql/my.cnf -p 33307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

从库容器设置

docker run -di -v /root/mysql2/data/:/var/lib/mysql -v /root/mysql2/conf.d:/etc/mysql/conf.d -v /root/mysql2/my.cnf:/etc/mysql/my.cnf -p 33306:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
docker ps 可查看运行的mysql容器

连接主库

mysql -uroot -P33307 -h 10.0.0.200 -p123456

再主库创建用户并授予所以权限

创建用户test

create user 'test'@'%' identified by '123';

授权

grant all privileges on *.* to 'test'@'%' ;

刷新权限

flush privileges;

查看主状态

show master status;

连接从数据库

change master to master_host='10.0.0.200',master_port=33307,master_user='test',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=0;

命令详细解释

  • change master to
  • master_host='MySQL主服务器IP地址',
  • master_user='之前在MySQL主服务器上面创建的用户名',
  • master_password='之前创建的密码',
  • master_log_file='MySQL主服务器状态中的二进制文件名',
  • master_log_pos='MySQL主服务器状态中的position值';

这时在主数据库中写入数据,可在从数据库中查看;

注若测试在从数据库中写入数据会导致主从冲突,造成主从断开

可以通过下发如下命令解决

stop slave; # 先停止主从库

set GLOBAL SQL_SLAVE_SKIP_COUNTER=2; # 这里是跳过binlog的命令条数

start slave; # 启动主从就ok了

django的多数据的读写分离

复制代码
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'db1': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db1.sqlite3',
    }
}

migrate --database db1 app01 # 迁移指定数据库

手动测试读写分离:

Book.objects.using('db1').create(name='xxx')

自动测试读写分离:

class DBRouter(object):

def db_for_read(self, model, **hints):

多个从库 ['db1','db2','db3']

model是哪个模型表

return 'db1'

def db_for_write(self, model, **hints):

return 'default'
DATABASE_ROUTERS = ['utils.db_router.DBRouter', ] # 配置setting

借鉴博客:https://www.cnblogs.com/clever-cat/p/17356820.html

相关推荐
Lx3524 小时前
排序缓冲区调优:sort_buffer_size的合理配置
sql·mysql·性能优化
feifeigo1239 天前
Java 正则表达式高级用法
java·mysql·正则表达式
敏叔V5879 天前
大模型Text2SQL之在CentOS上使用yum安装与使用MySQL
linux·mysql·centos
程序猿小D9 天前
[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+Vue实现的校园二手交易平台管理系统,推荐!
java·数据库·mysql·spring·vue·毕业设计·校园二手交易平台
张太行_9 天前
MySQL与Excel比较
数据库·mysql·excel
斯普信专业组9 天前
MySQL 8.x配置MGR高可用+ProxySQL读写分离(二):ProxySQL配置MySQL代理及读写分离
数据库·mysql
中国lanwp9 天前
InnoDB Cluster 与 NDB Cluster 对比及部署指南
mysql
亲爱的非洲野猪9 天前
MySQL 事务实现机制详解
数据库·mysql
程序员岳焱9 天前
Java 与 MySQL 性能优化:MySQL性能指标解读与监控方法
后端·mysql·性能优化
i小溪9 天前
着重介绍一下sql语句中的JSON_UNQUOTE、JSON_EXTRACT
数据库·mysql