使用数据库的正确姿势(一)

题图

这是我在慕课网上分享的一个关于数据库操作的逐字讲稿,主要分两部分,第一部分为数据库的基本使用,第二部分为用面向对象的方法来使用数据库,及分布式数据库的基本介绍。

大家好,今天我给大家分享的主题是《使用数据库的正确姿势》,首先我会对数据库做一个简要的介绍,然后我会从三个方面来讲解如何使用数据库,下面我们正式开始。

数据库的重要性

众所周知,数据库是互联网公司最宝贵的资源,我们可以从两个角度来看它的重要性:

从用户角度看,它保存了用户的数据,任何数据的丢失都会影响产品体验,更为严重者,数据库的使用问题还会导致用户的财产损失,例如某个用户进行了两笔支付操作,但在数据库中只生成了一笔订单,此为常见的数据一致性问题。

从公司角度,数据库是公司的财富,也是公司间竞争的壁垒,拥有更大数据规模的公司,相应的也会更有优势,尤其是在大数据时代,更多的数据意味着有更多的可能性,以及更好的用户体验,同时也更难被超越,例如国内的腾讯、阿里巴巴、百度,及国外的Google、Facebook等公司就是典型的例子。

数据库领域

所以说任何公司或者开发者,都要用好数据库(我们这里说的数据库指的是关系型数据库),由于数据库足够复杂,在计算机领域,它已经发展成了一个独立的方向。而作为一个开发者,能不能用好数据库,也成了衡量他是否有价值的指标,在招聘中,我经常会问面试者一个关于数据库的问题:

对于MySQL,你认为它的瓶颈在哪里?

这个问题看似简单,但得到的答案可以用千差万别来形容,答案大致分这么几种:

1. 数据库的容量是它的瓶颈
2. 大量的读或写操作是它的瓶颈
3. 复杂的SQL语句是它的瓶颈,例如大量没有经过优化的SQL语句
4. 索引越来越大是它瓶颈

这个问题看似是一个数据库问题,实际上它还是一个操作系统问题,因为数据库和操作系统一样,也要使用内存,磁盘,网络,同时还要对缓存进行高效的利用和管理,并且它比操作系统还要擅长于存储和管理数据。说到这里,我倒要反过来问你一个问题:

如果你的电脑变慢了,你会怎么做?

大多数人第一时间会想到加条内存,或换个SSD硬盘,这个问题很少有人会回答错误,那么为什么我们回答同样的问题,只是把操作系统换成数据库,就回答不上来了呢?

所以,能不能举一反三,及清楚的认识操作系统和数据库的组成原理,直接反映了这个人的基本功是否扎实,以及他以后能不能写出高质量的代码。

数据库的应用

在数据库的应用方面,一般又分为两种角色:

  • 一种是应用开发者,在公司里一般被称为“服务器工程师”或“web开发工程师”
  • 一种是数据库管理者,在公司一般被称为“DBA”(DataBase Administrator)或“运维”

这两种角色的视角和侧重点是不一样的,前者一般侧重于在应用程序中使用数据库,他们的日常操作即我们常说的CRUD操作(分别是create、read、update和delete);而后者则更侧重于数据库的维护和管理,例如安全性、扩展性、性能、及易用性等。这次的分享主要会围绕第一个角色展开。

虽然一般公司常会把这两种角色分配在不同的岗位,但任何一种角色最好能拥有另外一种角色的思维,这样才能更高效的使用数据库,增强组织间的协作,从而提升整体的开发和维护效率。

下面会以Python语言和MySQL数据库为例,从数据库的应用方面讲一下在工作中,如何更好的使用数据库。

使用Python的原因是因为Python语言比较简洁,在业内使用非常广泛,且它的数据库方面的资源比较完善;而MySQL基本是最为常用的数据库。

在我看来,数据库的使用方面分为三个层次

  1. 数据库的基本使用
  2. 利用面向对象的思维使用数据库
  3. 在项目中应用分布式数据库

在我经历的大多数项目中,我发现很多项目仅仅停留在第一个层次,尤其是,小的团队对数据库的使用都比较初级,他们可能更关注数据库的设计三范式、数据库的基本操作,及设计出来的数据库能否满足应用的需求,对于应用的可维护性和扩展性可能会关注的比较少。

但我认为在数据库的使用方面,起码要从第二个层次开始(具体原因后面会详细介绍),即小团队、小项目使用面向对象的思维使用数据库,等到项目变大了,再由第二个层次扩展到第三个层次。

数据库的环境搭建

下面我们进入数据库的基本使用,不过在此之前,我们首先需要搭建开发环境,我当前的演示环境是macOS,对于其他操作系统,我将提供以下页面供大家参考:

下面我来演示一下操作步骤

# 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语句,向数据库中插入一条数据,这条数据的nameraw1
第2步 - 我们执行Select语句,将这条数据读取出来
第3步 - 我们执行Update语句,用另外一个名字raw,来替换raw1
第4步 - 我们执行Delete语句,把这条记录删除

运行后,你可以看到在第2步中我们把插入的数据查询出来,它的nameraw1,第3步我们把name修改为了raw,第4步,我们把记录删除后,打印出来的是空的记录

(2L, 'raw1')
[(2L, 'raw')]
[]

了解以上几个基本的操作,你便可以开始使用数据库,这就是我们前面提到的数据库应用的第一个层次。

以上代码均可以在github上下载

本文是《使用数据库的正确姿势》系列文章的第一篇,你可以打开《使用数据库的正确姿势(二)》继续阅读

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容