ubuntu安装MySQL:
- 安装:
sudo apt-get install mysql-server mysql-client
- 重启:
service mysql restart
- 停止:
service mysql stop
- 查询服务是否启动:
netstat -tap | grep mysql
允许远程连接
找到mysql配置文件并修改
- sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
- 将bind-address=127.0.0.1注释
登录mysql,运行命令
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
记得输入自己的密码,.:第一个代表数据库名;第二个代表表名。这里的意思是所有数据库里的所有表都授权给用户。root:授予root账号。“%”:表示授权的用户IP可以指定,这里代表任意的IP地址都能访问MySQL数据库。“password”:分配账号对应的密码,这里密码自己替换成你的mysql root帐号密码。
flush privileges;
- 刷新权限信息,也即是让我们所作的设置马上生效。
- 重启mysql
sudo /etc/init.d/mysql restart
sudo service mysql restar
- 如果要修改root密码:
set password for "root"@localhost=password("root");
卸载管理:
删除mysql的数据文件:sudo rm /var/lib/mysql/ -R
删除mqsql的配置文件:sudo rm /etc/mysql/ -R
卸载mysql的程序:
sudo apt-get autoremove mysql* --purge
sudo apt-get remove apparmor
约束的目的:保证数据的正确性。
-
主键primary key,默认是唯一,标识这一行数据与其它不同。非空并唯一
-
非空not null,默认是NULL
-
惟一unique
-
默认default
- 外键foreign key(外键表)references 主键表(主键表名)类型一致。
- 如果有主外键,先创建主键表,再创建外键表。
- 如果有主外键,先删除外键表,再删主键表。
主键的生成策略
int auto_increment
create table grade(
gid int auto_increment primary key,
gname varchar(20) unique not null
);
- 增:insert into 表名(列名) values(与列表对应的值);
- 删: delete from 表名 [where 条件];
- 改: update 表名set 列名=值,列名=值[where 条件]
- 查询:
select * from 表名; 查询所有;
select 列名 [改别名],列名 from 表名 [where 条件]
索引:create index 索引名称 on 表名(列名)
高级查询:
#分组
select
from
where 分组之前的过滤
group by
having 分组之后的过滤
limit
对比where与having
- where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
- having是对group by的结果进行筛选
排序
为了方便查看数据,可以对数据进行排序
select * from 表名
order by 列1 asc|desc,列2 asc|desc,...
分页
当数据量过大时,在一页中查看数据是一件非常麻烦的事情
select * from 表名
limit start,count
从start开始,获取count条数据
start索引从0开始
视图
-对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情
解决:定义视图
-视图本质就是对查询的一个封装,虚拟的表,一旦封装的内容改变了,视图的内容也随着用
事务四大特性(简称ACID)
- 原子性:一组事务,要么成功;要么撤回。
- 稳定性 :有非法数据(外键约束之类),事务撤回。
- 隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
- 可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可兼得,
innodb_flush_log_at_trx_commit 选项 决定什么时候吧事务保存到日志里。
事务语句
- 开启begin; 或者 start transaction;
- 提交commit;
- 回滚rollback;
mysql事务隔离级别
- Read Uncommitted(读取未提交内容)
- 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
- 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。
- 在提交读(READ COMMITTED)级别中,基于锁机制并发控制的DBMS需要对选定对象的写锁(write locks)一直保持到事务结束,但是读锁(read locks)在SELECT操作完成后马上释放(因此“不可重复读”现象可能会发生,见下面描述)。和前一种隔离级别一样,也不要求“范围锁(range-locks)”。
- 简而言之,提交读这种隔离级别保证了读到的任何数据都是提交的数据,避免读到中间的未提交的数据,脏读(dirty reads)。但是不保证事务重新读的时候能读到相同的数据,因为在每次数据读完之后其他事务可以修改刚才读到的数据。
- 提交读保证我们读到的数据都是事务提交后的数据,这样子就保证了程序中数据的正确性,在我们的应用中,基本都是使用的Read Commited隔离级别。
Repeatable Read(可重读)
- 这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)
- Serializable(可串行化)
- 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
- 这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。
- 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
- 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
- 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几行(Row)数据,而另一个事务却在此时插入了新的几行数据,先前的事务在接下来的查询中,就会发现有几行数据是它先前所没有的。
设置mysql事务的隔离级别
- 打开mysql配置文件: sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf, 添加如下行。
#transaction-isolation =READ-COMMITTED
保存配置文件,重启mysql服务。
- sudo service mysql restart
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
创建索引
- 如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
- 字段类型如果不是字符串,可以不填写长度部分
- create index 索引名称 on 表名(字段名称(长度))
删除索引:
- drop index 索引名称 on 表名;
索引demo
- 1)创建测试表testindex
- create table test_index(title varchar(10));
- 2)使用python程序(ipython也可以)通过pymsql模块 向表中加入十万条数据
from pymysql import connect
def main():
# 创建Connection连接
conn = connect(host='localhost',port=3306,database='mydb',user='root',password='root',charset='utf8')
# 获得Cursor对象
cursor = conn.cursor()
# 插入10万次数据
for i in range(100000):
cursor.execute("insert into test_index values('ha-%d')" % i)
# 提交数据
conn.commit()
if __name__ == "__main__":
main()
查看执行的时间:
- show profiles;
- 为表title_index的title列创建索引:create index title_index on test_index(title(10));
- 执行查询语句:select * from test_index where title=‘ha-99999’;
- 再次查看执行的时间:show profiles;
创建账户、授权
- 需要使用实例级账户登录后操作,以root为例
- 常用权限主要包括:create、alter、drop、insert、update、delete、select
- 如果分配所有权限,可以使用all privileges
创建账户&授权
- grant 权限列表 on 数据库 to ‘用户名’@‘访问主机’ identified by ‘密码’;
创建账户并授予所有权限
grant select on xxdb.* to 'laowang'@'localhost' identified by '123456';
- 可以操作python数据库的所有表,方式为: xxdb.*
- 访问主机通常使用 百分号% 表示此账户可以使用任何ip的主机登录访问此数据库
- 访问主机可以设置成 localhost或具体的ip,表示只允许本机或特定主机访问
查看用户有哪些权限
-
show grants for ‘laowang’@’localhost’;
-
- 修改权限
grant 权限名称 on 数据库 to 账户@主机 with grant option;
-
- 修改密码
#使用root登录,修改mysql数据库的user表,使用password()函数进行密码加密
update user set authentication_string=password('新密码') where user='用户名';
例:update user set authentication_string=password('123') where user='laowang';
注意修改完成后需要刷新权限
- 刷新权限:flush privileges
删除账户
- 语法1:使用root登录
- drop user ‘用户名’@‘主机’;
- 例:drop user ‘laowang’@’%’;
- 语法2:使用root登录,删除mysql数据库的user表中数据
- delete from user where user=‘用户名’;
- 例:delete from user where user=‘laowang’;
- – 操作结束之后需要刷新权限
- flush privileges
忘记 root 账户密码怎么办 !!
配置主从同步的基本步骤
- 在主服务器上,必须开启二进制日志机制和配置一个独立的ID
- 在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号
- 在开始复制进程前,在主服务器上记录二进制文件的位置信息
- 如果在开始复制之前,数据库中已经有数据,就必须先创建一个数据快照(可以使用mysqldump导出数据库,或者直接复制数据文件)
- 配置从服务器要连接的主服务器的IP地址和登陆授权,二进制日志文件名和位置
详细配置主从同步的方法
-
主和从的身份可以自己指定,我们将虚拟机Ubuntu中MySQL作为主服务器,将Windows中的MySQL作为从服务器。 在主从设置前,要保证Ubuntu与Windows间的网络连通。
-
备份主服务器原有数据到从服务器
-
如果在设置主从同步前,主服务器上已有大量数据,可以使用mysqldump进行数据备份并还原到从服务器以实现数据的复制。
在主服务器Ubuntu上进行备份,执行命令:
mysqldump -uroot -pmysql --all-databases --lock-all-tables > ~/master_db.sql
--all-databases :导出所有数据库
--lock-all-tables :执行操作时锁住所有表,防止操作时有数据修改
~/master_db.sql :导出的备份数据(sql文件)位置,可自己指定
在从服务器Windows上进行数据还原
登陆数据库,然后运行
source master_db.sql
悲观锁(Pessimistic Lock)
- 在查询的时候,锁起来,事务结束后,释放。
- 悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select… for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。
- 这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。
乐观锁(Optimistic Lock)
- 查询的时候,不需要操作,更改的时候再判断。
- 乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。
- 乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:
- SELECT data AS old_data, version AS old_version FROM …;
- 根据获取的数据进行业务操作,得到new_data和new_version
- UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {
// 乐观锁获取成功,操作完成
} else {
// 乐观锁获取失败,回滚并重试
}
- 乐观锁是否在事务中其实都是无所谓的,其底层机制是这样:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,直到这一行被成功更新后才释放。因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,即可确认这之间没有发生并发的修改。如果更新失败即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。
- 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能
- 乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方