使用数据库的正确姿势(一)
这是我在慕课网上分享的一个关于数据库操作的逐字讲稿,主要分两部分,第一部分为数据库的基本使用,第二部分为用面向对象的方法来使用数据库,及分布式数据库的基本介绍。
大家好,今天我给大家分享的主题是《使用数据库的正确姿势》,首先我会对数据库做一个简要的介绍,然后我会从三个方面来讲解如何使用数据库,下面我们正式开始。
数据库的重要性
众所周知,数据库是互联网公司最宝贵的资源,我们可以从两个角度来看它的重要性:
从用户角度看,它保存了用户的数据,任何数据的丢失都会影响产品体验,更为严重者,数据库的使用问题还会导致用户的财产损失,例如某个用户进行了两笔支付操作,但在数据库中只生成了一笔订单,此为常见的数据一致性问题。
从公司角度,数据库是公司的财富,也是公司间竞争的壁垒,拥有更大数据规模的公司,相应的也会更有优势,尤其是在大数据时代,更多的数据意味着有更多的可能性,以及更好的用户体验,同时也更难被超越,例如国内的腾讯、阿里巴巴、百度,及国外的Google、Facebook等公司就是典型的例子。
数据库领域
所以说任何公司或者开发者,都要用好数据库(我们这里说的数据库指的是关系型数据库),由于数据库足够复杂,在计算机领域,它已经发展成了一个独立的方向。而作为一个开发者,能不能用好数据库,也成了衡量他是否有价值的指标,在招聘中,我经常会问面试者一个关于数据库的问题:
对于MySQL,你认为它的瓶颈在哪里?
这个问题看似简单,但得到的答案可以用千差万别来形容,答案大致分这么几种:
1. 数据库的容量是它的瓶颈
2. 大量的读或写操作是它的瓶颈
3. 复杂的SQL语句是它的瓶颈,例如大量没有经过优化的SQL语句
4. 索引越来越大是它瓶颈
这个问题看似是一个数据库问题,实际上它还是一个操作系统问题,因为数据库和操作系统一样,也要使用内存,磁盘,网络,同时还要对缓存进行高效的利用和管理,并且它比操作系统还要擅长于存储和管理数据。说到这里,我倒要反过来问你一个问题:
如果你的电脑变慢了,你会怎么做?
大多数人第一时间会想到加条内存,或换个SSD硬盘,这个问题很少有人会回答错误,那么为什么我们回答同样的问题,只是把操作系统换成数据库,就回答不上来了呢?
所以,能不能举一反三,及清楚的认识操作系统和数据库的组成原理,直接反映了这个人的基本功是否扎实,以及他以后能不能写出高质量的代码。
数据库的应用
在数据库的应用方面,一般又分为两种角色:
- 一种是应用开发者,在公司里一般被称为“服务器工程师”或“web开发工程师”
- 一种是数据库管理者,在公司一般被称为“DBA”(DataBase Administrator)或“运维”
这两种角色的视角和侧重点是不一样的,前者一般侧重于在应用程序中使用数据库,他们的日常操作即我们常说的CRUD操作(分别是create、read、update和delete);而后者则更侧重于数据库的维护和管理,例如安全性、扩展性、性能、及易用性等。这次的分享主要会围绕第一个角色展开。
虽然一般公司常会把这两种角色分配在不同的岗位,但任何一种角色最好能拥有另外一种角色的思维,这样才能更高效的使用数据库,增强组织间的协作,从而提升整体的开发和维护效率。
下面会以Python语言和MySQL数据库为例,从数据库的应用方面讲一下在工作中,如何更好的使用数据库。
使用Python的原因是因为Python语言比较简洁,在业内使用非常广泛,且它的数据库方面的资源比较完善;而MySQL基本是最为常用的数据库。
在我看来,数据库的使用方面分为三个层次
- 数据库的基本使用
- 利用面向对象的思维使用数据库
- 在项目中应用分布式数据库
在我经历的大多数项目中,我发现很多项目仅仅停留在第一个层次,尤其是,小的团队对数据库的使用都比较初级,他们可能更关注数据库的设计三范式、数据库的基本操作,及设计出来的数据库能否满足应用的需求,对于应用的可维护性和扩展性可能会关注的比较少。
但我认为在数据库的使用方面,起码要从第二个层次开始(具体原因后面会详细介绍),即小团队、小项目使用面向对象的思维使用数据库,等到项目变大了,再由第二个层次扩展到第三个层次。
数据库的环境搭建
下面我们进入数据库的基本使用,不过在此之前,我们首先需要搭建开发环境,我当前的演示环境是macOS,对于其他操作系统,我将提供以下页面供大家参考:
- MySQL的安装页面
- pip的安装说明文档,多啰嗦一句,你最好配置一个pip的国内镜像(例如豆瓣镜像或清华大学镜像),这样你在安装软件时速度会快很多。
- 对于macOS环境,你还需要配置homebrew的镜像
下面我来演示一下操作步骤
# 1. 安装pip
$ wget https://bootstrap.pypa.io/get-pip.py
$ python ./get-pip.py
# 2. 配置pip源
$ echo "[global]" > ~/.pip/pip.conf
$ echo "index-url = https://pypi.tuna.tsinghua.edu.cn/simple" >> ~/.pip/pip.conf
# 3. 检查pip源文件
$ cat ~/.pip/pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
# 4. 安装MySQL
$ brew install mysql
==> Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/mysql-5.7.17.sierra.bottle.tar.gz
Already downloaded: /Users/fengyajie/Library/Caches/Homebrew/mysql-5.7.17.sierra.bottle.tar.gz
==> Pouring mysql-5.7.17.sierra.bottle.tar.gz
==> Using the sandbox
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
mysql_secure_installation
To connect run:
mysql -uroot
To have launchd start mysql now and restart at login:
brew services start mysql
Or, if you don't want/need a background service you can just run:
mysql.server start
==> Summary
🍺 /usr/local/Cellar/mysql/5.7.17: 14,226 files, 444.4M
# 5. mysql在mac上的初始用户是root,没有密码,你可以通过命令行`mysql -uroot`启动MySQL,如果没问题,键入quit退出
$ mysql -uroot
# 6. 安装MySQL-python
$ pip install MySQL-python
# 7. 安装SQLAlchemy
$ pip install SQLAlchemy
完成以上7步,你的python-mysql开发环境就搭建好了
数据库的基本使用
下面我们正式进入数据库的基本使用环节,数据库的基本使用主要包括DDL(Data Definition Language)和DML(Data Manipulation Language),我们用具体的操作来理解这两个概念:
- 常用的DDL操作为创建数据库(create database)、创建表(create table)和修改表(alter table)
- 常用的DML操作为CRUD,包括新增(Create)、查找(Read)、修改(Update)及删除(Delete)四种基本操作,对应到数据库的命令为Insert、Select、Update和Delete
创建数据库
首先,我们来看一下创建数据库的代码
def getURL(user, passwd, host, port, database="", driver="mysql"):
mysql_db = {'drivername': driver,
'username': user,
'password': passwd,
'host': host,
'port': port,
'database': database}
return URL(**mysql_db)
def createDatabase(user, passwd, host, port, db):
db_uri = getURL(user, passwd, host, port) # 步骤1
engine = create_engine(db_uri) # 步骤2
engine.execute("create database if not exists %s" % db) # 步骤3
createDatabase("root", "", "localhost", 3306, "mydb")
createDatabase
这个函数实现了创建数据库的三个步骤:
步骤1 - 获取数据库的地址
步骤2 - 连接数据库
步骤3 - 执行创建数据库的命令
运行这段代码后,我们通过命令行(输入mysql -uroot
)打开数据库,执行show databases;
命令,这时你便可以看到我们刚创建的数据库mydb了。
$ mysql -uroot
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 5.7.17 Homebrew
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| mydb |
+--------------------+
5 rows in set (0.00 sec)
创建表
接着我们来看一下创建表的代码
def testCreateTable():
db_uri = getURL("root", "", "localhost", 3306, "mydb")
engine = create_engine(db_uri) # 步骤1
metadata = MetaData(engine)
table = Table('EX1', metadata,
Column('id', Integer, primary_key=True, autoincrement=True),
Column('name', String(255), nullable=False)) # 步骤2
table.create() # 步骤3
testCreateTable()
testCreateTable这个函数实现了创建表,同样分为三个步骤:
步骤1 - 连接数据库
步骤2 - 定义表的元数据
步骤3 - 创建数据表
步骤2中指定了表名为EX1
,该表有2个字段,一个字段为id
,另一个为name
。运行该程序后,你会发现,数据库mydb
中多了一个表EX1
CRUD
最后,我们再来看一下CRUD的代码,这段代码在testCRUD函数中
def testCRUD():
db_uri = getURL("root", "", "localhost", 3306, "mydb")
engine = create_engine(db_uri)
# 第1步 Create
engine.execute('INSERT INTO EX1 '
'(name) '
'VALUES ("raw1")')
# 第2步 Read
result = engine.execute('SELECT * FROM EX1')
for _r in result:
print _r
# 第3步 Update
engine.execute('UPDATE EX1 set name="raw" '
'WHERE name="raw1"')
result = engine.execute('SELECT * FROM EX1')
for _r in result:
print _r
# 第4步 Delete
engine.execute('DELETE from EX1 where name="raw"')
result = engine.execute('SELECT * FROM EX1')
print result.fetchall()
testCRUD()
第1步 - 我们执行Insert语句,向数据库中插入一条数据,这条数据的name
为raw1
第2步 - 我们执行Select语句,将这条数据读取出来
第3步 - 我们执行Update语句,用另外一个名字raw
,来替换raw1
第4步 - 我们执行Delete语句,把这条记录删除
运行后,你可以看到在第2步中我们把插入的数据查询出来,它的name
为raw1
,第3步我们把name
修改为了raw
,第4步,我们把记录删除后,打印出来的是空的记录
(2L, 'raw1')
[(2L, 'raw')]
[]
了解以上几个基本的操作,你便可以开始使用数据库,这就是我们前面提到的数据库应用的第一个层次。
以上代码均可以在github上下载
本文是《使用数据库的正确姿势》系列文章的第一篇,你可以打开《使用数据库的正确姿势(二)》继续阅读