first commit
This commit is contained in:
commit
ba848e218d
1001 changed files with 152333 additions and 0 deletions
210
数据库/mongodb/MongoDB数据表基本操作.html
Normal file
210
数据库/mongodb/MongoDB数据表基本操作.html
Normal file
|
@ -0,0 +1,210 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="tool" content="leanote-desktop-app">
|
||||
<title>MongoDB数据表基本操作</title>
|
||||
<style>
|
||||
|
||||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*公用文字样式*/
|
||||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||||
.note-container{
|
||||
width:850px;
|
||||
margin:auto;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 1px 1px 10px #eee;
|
||||
}
|
||||
#title {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin-bottom: 16px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: none;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
table tr:nth-child(2n) {
|
||||
background-color: rgb(247, 247, 249);
|
||||
}
|
||||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||||
border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
blockquote {
|
||||
border-left-width:10px;
|
||||
background-color:rgba(128,128,128,0.05);
|
||||
border-top-right-radius:5px;
|
||||
border-bottom-right-radius:5px;
|
||||
padding:15px 20px;
|
||||
border-left:5px solid rgba(128,128,128,0.075);
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom:1.1em;
|
||||
font-size:1em;
|
||||
line-height:1.45
|
||||
}
|
||||
blockquote ul:last-child,blockquote ol:last-child {
|
||||
margin-bottom:0
|
||||
}
|
||||
pre {
|
||||
padding: 18px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
font-size: 90%;
|
||||
color: #c7254e;
|
||||
white-space: nowrap;
|
||||
background-color: #f9f2f4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footnote {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
pre {
|
||||
word-break:break-word
|
||||
}
|
||||
p,pre,pre.prettyprint,blockquote {
|
||||
margin:0 0 1.1em
|
||||
}
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
.sequence-diagram,.flow-chart {
|
||||
text-align:center;
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
.sequence-diagram text,.flow-chart text {
|
||||
font-size:15px !important;
|
||||
font-family:"Source Sans Pro",sans-serif !important
|
||||
}
|
||||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||||
fill:#f6f6f6
|
||||
}
|
||||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||||
stroke:#3f3f3f
|
||||
}
|
||||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||||
stroke:none
|
||||
}
|
||||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||||
fill:#3f3f3f
|
||||
}
|
||||
ul,ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
ul ul,ol ul,ul ol,ol ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
kbd {
|
||||
padding:.1em .6em;
|
||||
border:1px solid rgba(63,63,63,0.25);
|
||||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
font-size:.7em;
|
||||
font-family:sans-serif;
|
||||
background-color:#fff;
|
||||
color:#333;
|
||||
border-radius:3px;
|
||||
display:inline-block;
|
||||
margin:0 .1em;
|
||||
white-space:nowrap
|
||||
}
|
||||
.toc ul {
|
||||
list-style-type:none;
|
||||
margin-bottom:15px
|
||||
}
|
||||
</style>
|
||||
<!-- 该css供自定义样式 -->
|
||||
<link href="../leanote-html.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="note-container">
|
||||
<h1 class="title" id="leanote-title">MongoDB数据表基本操作</h1>
|
||||
<div class="content-html" id="leanote-content"><p>查看全部数据表</p><pre id="leanote_ace_1479781232163_0" class="brush:sh ace-tomorrow">> use ChatRoom
|
||||
switched to db ChatRoom
|
||||
> show collections
|
||||
Account
|
||||
Chat
|
||||
system.indexes
|
||||
system.users</pre><p>创建数据表</p><pre id="leanote_ace_1479781278873_0" class="brush:sh ace-tomorrow">> db.createCollection("Account")
|
||||
{"ok":1}</pre><pre id="leanote_ace_1479781293825_0" class="brush:sh ace-tomorrow">> db.createCollection("Test",{capped:true, size:10000}) { "ok" : 1 }
|
||||
{"ok":1}</pre><p>-- 说明</p><p>capped:true,表示该集合的结构不能被修改;</p><p>size:在建表之初就指定一定的空间大小,接下来的插入操作会不断地按顺序APPEND数据在这个预分配好空间的文件中,如果已经超出空间大小,则回到文件头覆盖原来的数据继续插入。这种结构保证了插入和查询的高效性,它不允许删除单个记录,更新的也有限制:不能超过原有记录的大小。这种表效率很高,它适用于一些暂时保存数据的场合,比如网站中登录用户的session信息,又比如一些程序的监控日志,都是属于过了一定的时间就可以被覆盖的数据。</p><p> <br></p><p>修改数据表名</p><pre id="leanote_ace_1479781320849_0" class="brush:sh ace-tomorrow">> db.Account.renameCollection("Account1")
|
||||
{ "ok" : 1 }</pre><p> <br></p><p>数据表帮助主题help</p><pre id="leanote_ace_1479781866930_0" class="brush:sh ace-tomorrow">> db.Account.help()
|
||||
DBCollection help
|
||||
db.Account.find().help() - show DBCursor help
|
||||
db.Account.count()
|
||||
db.Account.dataSize()
|
||||
db.Account.distinct( key ) - eg. db.Account.distinct( 'x' )
|
||||
db.Account.drop() drop the collection
|
||||
db.Account.dropIndex(name)
|
||||
db.Account.dropIndexes()
|
||||
db.Account.ensureIndex(keypattern[,options]) - options is an object with these possible fields: name, unique, dropDups
|
||||
db.Account.reIndex()
|
||||
db.Account.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to retur.
|
||||
|
||||
e.g. db.Account.find( {x:77} , {name:1, x:1} )
|
||||
db.Account.find(...).count()
|
||||
db.Account.find(...).limit(n)
|
||||
db.Account.find(...).skip(n)
|
||||
db.Account.find(...).sort(...)
|
||||
db.Account.findOne([query])
|
||||
db.Account.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )
|
||||
db.Account.getDB() get DB object associated with collection
|
||||
db.Account.getIndexes()
|
||||
db.Account.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )
|
||||
db.Account.mapReduce( mapFunction , reduceFunction , <optional params> )
|
||||
db.Account.remove(query)
|
||||
db.Account.renameCollection( newName , <dropTarget> ) renames the collection.
|
||||
db.Account.runCommand( name , <options> ) runs a db command with the given name where the first param is the collection name
|
||||
db.Account.save(obj)
|
||||
db.Account.stats()
|
||||
db.Account.storageSize() - includes free space allocated to this collection
|
||||
db.Account.totalIndexSize() - size in bytes of all the indexes
|
||||
db.Account.totalSize() - storage allocated for all data and indexes
|
||||
db.Account.update(query, object[, upsert_bool, multi_bool])
|
||||
db.Account.validate() - SLOW
|
||||
db.Account.getShardVersion() - only for use with sharding </pre><p> <br></p><p>查看全部表记录</p><pre id="leanote_ace_1479782012602_0" class="brush:sh ace-tomorrow">> db.Account.find()
|
||||
{ "_id" : ObjectId("4df08553188e444d001a763a"), "AccountID" : 1, "UserName" : "libing", "Password" : "1", "Age" : 26, "Email" : "libing@126.com", "RegisterDate" : "2011-06-09 16:31:25" }
|
||||
{ "_id" : ObjectId("4df08586188e444d001a763b"), "AccountID" : 2, "UserName" : "lb", "Password" : "1", "Age" : 25, "Email" : "libing@163.com", "RegisterDate" : "2011-06-09 16:36:95" }</pre><p> <br></p></div>
|
||||
</div>
|
||||
|
||||
<!-- 该js供其它处理 -->
|
||||
<script src="../leanote-html.js"></script>
|
||||
</body>
|
||||
</html>
|
165
数据库/mongodb/mongodb-数据库操作-备份-还原-导出-导入.html
Normal file
165
数据库/mongodb/mongodb-数据库操作-备份-还原-导出-导入.html
Normal file
File diff suppressed because one or more lines are too long
8
数据库/mongodb/导入导出数据.md
Normal file
8
数据库/mongodb/导入导出数据.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
导出
|
||||
```
|
||||
mongodump -h xxx -d dbname -u dbuser -o dir
|
||||
```
|
||||
导入
|
||||
```
|
||||
mongorestore -h xxxxxx -d dbname -u dbuser dbfile
|
||||
```
|
5
数据库/mysql/B-tree与B+tree.md
Normal file
5
数据库/mysql/B-tree与B+tree.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
B树的非叶子节点也存储数据,而每层节点有16k大小(mysql),所以存储的数据会比较少
|
||||
B+树的非叶子节点上不存储数据,叶子节点包含所有索引字段,每层节点就会多存很多索引(8b索引+6b下级分叉的地址)
|
||||
|
||||
查询innodb的分页大小
|
||||
show gloobal status like 'innodb_page_size';
|
9
数据库/mysql/MHA和MGR.md
Normal file
9
数据库/mysql/MHA和MGR.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
mha在所有mysql节点上安装mha node,还需要安装mha manager,mha manager定时监控主节点的状态
|
||||
|
||||
从宕机崩溃的master保存二进制日志事件(binlog events);
|
||||
识别含有最新更新的slave;
|
||||
应用差异的中继日志(relay log)到其他slave;
|
||||
应用从master保存的二进制日志事件(binlog events);
|
||||
提升一个slave为新master;
|
||||
使用其他的slave连接新的master进行复制。
|
7
数据库/mysql/MVCC.md
Normal file
7
数据库/mysql/MVCC.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
在Mysql的InnoDB引擎中就是指在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于SELECT操作会访问版本链中的记录的过程。即对数据做了快照。
|
||||
|
||||
快照读 (snapshot read):读取的是记录的可见版本 (有可能是历史版本),不用加锁(共享读锁s锁也不加,所以不会阻塞其他事务的写)
|
||||
|
||||
当前读 (current read):读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录
|
||||
|
||||
InnoDB的MVCC,是通过在每行纪录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存了行的过期时间(或删除时间),当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行纪录的版本号进行比较
|
866
数据库/mysql/MySQL_5.6_Replication.md
Normal file
866
数据库/mysql/MySQL_5.6_Replication.md
Normal file
|
@ -0,0 +1,866 @@
|
|||
|
||||
|
||||
MySQL 5.6引入的GTID(Global Transaction IDs)使得其复制功能的配置、监控及管理变得更加易于实现,且更加健壮。
|
||||
|
||||
要在MySQL 5.6中使用复制功能,其服务配置段[mysqld]中至少应该定义如下选项:
|
||||
|
||||
binlog-format:二进制日志的格式,有row、statement和mixed几种类型;
|
||||
需要注意的是:当设置隔离级别为READ-COMMITED必须设置二进制日志格式为ROW,现在MySQL官方认为STATEMENT这个已经不再适合继续使用;但mixed类型在默认的事务隔离级别下,可能会导致主从数据不一致;
|
||||
log-slave-updates、gtid-mode、enforce-gtid-consistency、report-port和report-host:用于启动GTID及满足附属的其它需求;
|
||||
master-info-repository和relay-log-info-repository:启用此两项,可用于实现在崩溃时保证二进制及从服务器安全的功能;
|
||||
sync-master-info:启用之可确保无信息丢失;
|
||||
slave-paralles-workers:设定从服务器的SQL线程数;0表示关闭多线程复制功能;
|
||||
binlog-checksum、master-verify-checksum和slave-sql-verify-checksum:启用复制有关的所有校验功能;
|
||||
binlog-rows-query-log-events:启用之可用于在二进制日志记录事件相关的信息,可降低故障排除的复杂度;
|
||||
log-bin:启用二进制日志,这是保证复制功能的基本前提;
|
||||
server-id:同一个复制拓扑中的所有服务器的id号必须惟一;
|
||||
|
||||
|
||||
report-host:
|
||||
The host name or IP address of the slave to be reported to the master during slave registration. This value appears in the output of SHOW SLAVE HOSTS on the master server.
|
||||
|
||||
report-port:
|
||||
The TCP/IP port number for connecting to the slave, to be reported to the master during slave registration.
|
||||
|
||||
master-info-repository:
|
||||
The setting of this variable determines whether the slave logs master status and connection information to a FILE (master.info), or to a TABLE (mysql.slave_master_info)
|
||||
|
||||
relay-log-info-repository:
|
||||
This option causes the server to log its relay log info to a file or a table.
|
||||
|
||||
log_slave_updates:
|
||||
Whether updates received by a slave server from a master server should be logged to the slave's own binary log. Binary logging must be enabled on the slave for this variable to have any effect.
|
||||
|
||||
enforce_gtid_consistency:
|
||||
|
||||
|
||||
|
||||
|
||||
### 一、简单主从模式配置步骤
|
||||
|
||||
#### 1、配置主从节点的服务配置文件
|
||||
|
||||
1.1、配置master节点:
|
||||
```
|
||||
[mysqld]
|
||||
binlog-format=ROW
|
||||
log-bin=master-bin
|
||||
log-slave-updates=true
|
||||
gtid-mode=on
|
||||
enforce-gtid-consistency=true
|
||||
master-info-repository=TABLE
|
||||
relay-log-info-repository=TABLE
|
||||
sync-master-info=1
|
||||
slave-parallel-workers=2
|
||||
binlog-checksum=CRC32
|
||||
master-verify-checksum=1
|
||||
slave-sql-verify-checksum=1
|
||||
binlog-rows-query-log_events=1
|
||||
server-id=1
|
||||
report-port=3306
|
||||
port=3306
|
||||
datadir=/mydata/data
|
||||
socket=/tmp/mysql.sock
|
||||
report-host=master.magedu.com
|
||||
```
|
||||
|
||||
1.2、配置slave节点:
|
||||
```
|
||||
[mysqld]
|
||||
binlog-format=ROW
|
||||
log-slave-updates=true
|
||||
gtid-mode=on
|
||||
enforce-gtid-consistency=true
|
||||
master-info-repository=TABLE
|
||||
relay-log-info-repository=TABLE
|
||||
sync-master-info=1
|
||||
slave-parallel-workers=2
|
||||
binlog-checksum=CRC32
|
||||
master-verify-checksum=1
|
||||
slave-sql-verify-checksum=1
|
||||
binlog-rows-query-log_events=1
|
||||
server-id=11
|
||||
report-port=3306
|
||||
port=3306
|
||||
log-bin=mysql-bin.log
|
||||
datadir=/mydata/data
|
||||
socket=/tmp/mysql.sock
|
||||
report-host=slave.magedu.com
|
||||
```
|
||||
|
||||
#### 2、创建复制用户
|
||||
```
|
||||
mysql> GRANT REPLICATION SLAVE ON *.* TO repluser@172.16.100.7 IDENTIFIED BY 'replpass';
|
||||
```
|
||||
|
||||
说明:172.16.100.7是从节点服务器;如果想一次性授权更多的节点,可以自行根据需要修改;
|
||||
|
||||
#### 3、为备节点提供初始数据集
|
||||
|
||||
锁定主表,备份主节点上的数据,将其还原至从节点;如果没有启用GTID,在备份时需要在master上使用show master status命令查看二进制日志文件名称及事件位置,以便后面启动slave节点时使用。
|
||||
|
||||
#### 4、启动从节点的复制线程
|
||||
|
||||
如果启用了GTID功能,则使用如下命令:
|
||||
```
|
||||
mysql> CHANGE MASTER TO MASTER_HOST='master.magedu.com', MASTER_USER='repluser', MASTER_PASSWORD='replpass', MASTER_AUTO_POSITION=1;
|
||||
```
|
||||
没启用GTID,需要使用如下命令:
|
||||
```
|
||||
slave> CHANGE MASTER TO MASTER_HOST='172.16.100.6',
|
||||
-> MASTER_USER='repluser',
|
||||
-> MASTER_PASSWORD='replpass',
|
||||
-> MASTER_LOG_FILE='master-bin.000003',
|
||||
-> MASTER_LOG_POS=1174;
|
||||
```
|
||||
### 二、半同步复制
|
||||
|
||||
#### 1、分别在主从节点上安装相关的插件
|
||||
```
|
||||
master> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
|
||||
slave> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
|
||||
```
|
||||
#### 2、启用半同步复制
|
||||
|
||||
在master上的配置文件中,添加
|
||||
```
|
||||
rpl_semi_sync_master_enabled=ON
|
||||
```
|
||||
在至少一个slave节点的配置文件中添加
|
||||
```
|
||||
rpl_semi_sync_slave_enabled=ON
|
||||
```
|
||||
而后重新启动mysql服务即可生效。
|
||||
|
||||
|
||||
或者,也可以mysql服务上动态启动其相关功能:
|
||||
```
|
||||
master> SET GLOBAL rpl_semi_sync_master_enabled = ON;
|
||||
slave> SET GLOBAL rpl_semi_sync_slave_enabled = ON;
|
||||
slave> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
|
||||
```
|
||||
#### 3、确认半同步功能已经启用
|
||||
```
|
||||
master> CREATE DATABASE magedudb;
|
||||
master> SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
|
||||
|
||||
slave> SHOW DATABASES;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 三、MySQL Proxy
|
||||
|
||||
|
||||
#### 1、源码安装时,MySQL proxy的依赖关系:
|
||||
```
|
||||
libevent 1.x or higher (1.3b or later is preferred).
|
||||
lua 5.1.x or higher.
|
||||
glib2 2.6.0 or higher.
|
||||
pkg-config.
|
||||
libtool 1.5 or higher.
|
||||
MySQL 5.0.x or higher developer files.
|
||||
```
|
||||
#### 2、安装
|
||||
```
|
||||
# tar zxf mysql-proxy-0.8.2.tar.gz
|
||||
# cd mysql-proxy-0.8.2
|
||||
# ./configure
|
||||
# make
|
||||
|
||||
# make check
|
||||
```
|
||||
如果管理员有密码,上面的步骤则需要使用如下格式进行:
|
||||
```
|
||||
# MYSQL_PASSWORD=root_pwd make check
|
||||
|
||||
# make install
|
||||
```
|
||||
默认情况下, mysql-proxy安装在/usr/local/sbin/mysql-proxy,而Lua示例脚本安装在/usr/local/share目录中。
|
||||
|
||||
3、配置指令
|
||||
|
||||
mysql proxy的各配置参数请参见官方文档,http://dev.mysql.com/doc/refman/5.6/en/mysql-proxy-configuration.html
|
||||
|
||||
|
||||
使用rpm包在rhel6上安装mysql-proxy-0.8.2,其会提供配置文件及服务脚本,但没有提供读写分享的脚本。
|
||||
|
||||
|
||||
/etc/sysconfig/mysql-proxy文件用于定义mysql-proxy的启动参数。
|
||||
|
||||
ADMIN_USER – the user for the proxy's admin interface. You can leave the default admin user.
|
||||
ADMIN_PASSWORD – the password for the admin user in clear text. Change the default password for better security.
|
||||
ADMIN_LUA_SCRIPT – the admin script in the Lua programming language. Without this script the admin interface cannot work. You can leave the default value.
|
||||
PROXY_USER – the system user under which the proxy will work. By default it is mysql-proxy, and it's safe to leave it as is.
|
||||
PROXY_OPTIONS – proxy options such as logging level, plugins, and Lua scripts to be loaded.
|
||||
|
||||
|
||||
其中PROXY_OPTIONS是最常用的一个选项,用于定义mysql-proxy工作时的重要参数,例如:
|
||||
PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog --plugins=proxy --plugins=admin --proxy-backend-addresses=192.168.1.102:3306 --proxy-read-only-backend-addresses=192.168.1.105:3306 --proxy-lua-script=/usr/lib/mysql-proxy/lua/proxy/rw-splitting.lua"
|
||||
|
||||
|
||||
|
||||
### 四、安装配置mysql-proxy:
|
||||
|
||||
#### 4.1 下载所需要的版本,这里的系统平台为rhel6.4 32位系统,因此就以mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit.tar.gz为例。
|
||||
```
|
||||
# tar xf mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit.tar.gz -C /usr/local
|
||||
# cd /usr/local
|
||||
# ln -sv mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit mysql-proxy
|
||||
```
|
||||
添加代理用户
|
||||
```
|
||||
# useradd mysql-proxy
|
||||
```
|
||||
4.2 为mysql-proxy提供SysV服务脚本,内容如下所示
|
||||
```
|
||||
#!/bin/bash
|
||||
#
|
||||
# mysql-proxy This script starts and stops the mysql-proxy daemon
|
||||
#
|
||||
# chkconfig: - 78 30
|
||||
# processname: mysql-proxy
|
||||
# description: mysql-proxy is a proxy daemon for mysql
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
prog="/usr/local/mysql-proxy/bin/mysql-proxy"
|
||||
|
||||
# Source networking configuration.
|
||||
if [ -f /etc/sysconfig/network ]; then
|
||||
. /etc/sysconfig/network
|
||||
fi
|
||||
|
||||
# Check that networking is up.
|
||||
[ ${NETWORKING} = "no" ] && exit 0
|
||||
|
||||
# Set default mysql-proxy configuration.
|
||||
ADMIN_USER="admin"
|
||||
ADMIN_PASSWD="admin"
|
||||
ADMIN_LUA_SCRIPT="/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua"
|
||||
PROXY_OPTIONS="--daemon"
|
||||
PROXY_PID=/var/run/mysql-proxy.pid
|
||||
PROXY_USER="mysql-proxy"
|
||||
|
||||
# Source mysql-proxy configuration.
|
||||
if [ -f /etc/sysconfig/mysql-proxy ]; then
|
||||
. /etc/sysconfig/mysql-proxy
|
||||
fi
|
||||
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
echo -n $"Starting $prog: "
|
||||
daemon $prog $PROXY_OPTIONS --pid-file=$PROXY_PID --proxy-address="$PROXY_ADDRESS" --user=$PROXY_USER --admin-username="$ADMIN_USER" --admin-lua-script="$ADMIN_LUA_SCRIPT" --admin-password="$ADMIN_PASSWORD"
|
||||
RETVAL=$?
|
||||
echo
|
||||
if [ $RETVAL -eq 0 ]; then
|
||||
touch /var/lock/subsys/mysql-proxy
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
killproc -p $PROXY_PID -d 3 $prog
|
||||
RETVAL=$?
|
||||
echo
|
||||
if [ $RETVAL -eq 0 ]; then
|
||||
rm -f /var/lock/subsys/mysql-proxy
|
||||
rm -f $PROXY_PID
|
||||
fi
|
||||
}
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
if status -p $PROXY_PIDFILE $prog >&/dev/null; then
|
||||
stop
|
||||
start
|
||||
fi
|
||||
;;
|
||||
status)
|
||||
status -p $PROXY_PID $prog
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|status|condrestart|try-restart}"
|
||||
RETVAL=1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
||||
```
|
||||
将上述内容保存为/etc/rc.d/init.d/mysql-proxy,给予执行权限,而后加入到服务列表。
|
||||
```
|
||||
# chmod +x /etc/rc.d/init.d/mysql-proxy
|
||||
# chkconfig --add mysql-proxy
|
||||
```
|
||||
|
||||
|
||||
#### 4.3 为服务脚本提供配置文件/etc/sysconfig/mysql-proxy,内容如下所示:
|
||||
```
|
||||
# Options for mysql-proxy
|
||||
ADMIN_USER="admin"
|
||||
ADMIN_PASSWORD="admin"
|
||||
ADMIN_ADDRESS=""
|
||||
ADMIN_LUA_SCRIPT="/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua"
|
||||
PROXY_ADDRESS=""
|
||||
PROXY_USER="mysql-proxy"
|
||||
PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog"
|
||||
```
|
||||
|
||||
其中最后一行,需要按实际场景进行修改,例如:
|
||||
```
|
||||
PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog --plugins=proxy --plugins=admin --proxy-backend-addresses=172.16.100.6:3306 --proxy-read-only-backend-addresses=172.16.100.7:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua"
|
||||
```
|
||||
其中的proxy-backend-addresses选项和proxy-read-only-backend-addresses选项均可重复使用多次,以实现指定多个读写服务器或只读服务器。
|
||||
|
||||
#### 4.4 mysql-proxy的配置选项
|
||||
|
||||
mysql-proxy的配置选项大致可分为帮助选项、管理选项、代理选项及应用程序选项几类,下面一起去介绍它们。
|
||||
```
|
||||
--help
|
||||
--help-admin
|
||||
--help-proxy
|
||||
--help-all ———— 以上四个选项均用于获取帮助信息;
|
||||
|
||||
--proxy-address=host:port ———— 代理服务监听的地址和端口;
|
||||
--admin-address=host:port ———— 管理模块监听的地址和端口;
|
||||
--proxy-backend-addresses=host:port ———— 后端mysql服务器的地址和端口;
|
||||
--proxy-read-only-backend-addresses=host:port ———— 后端只读mysql服务器的地址和端口;
|
||||
--proxy-lua-script=file_name ———— 完成mysql代理功能的Lua脚本;
|
||||
--daemon ———— 以守护进程模式启动mysql-proxy;
|
||||
--keepalive ———— 在mysql-proxy崩溃时尝试重启之;
|
||||
--log-file=/path/to/log_file_name ———— 日志文件名称;
|
||||
--log-level=level ———— 日志级别;
|
||||
--log-use-syslog ———— 基于syslog记录日志;
|
||||
--plugins=plugin,.. ———— 在mysql-proxy启动时加载的插件;
|
||||
--user=user_name ———— 运行mysql-proxy进程的用户;
|
||||
--defaults-file=/path/to/conf_file_name ———— 默认使用的配置文件路径;其配置段使用[mysql-proxy]标识;
|
||||
--proxy-skip-profiling ———— 禁用profile;
|
||||
--pid-file=/path/to/pid_file_name ———— 进程文件名;
|
||||
|
||||
```
|
||||
|
||||
5、复制如下内容建立admin.lua文件,将其保存至/usr/local/mysql-proxy/share/doc/mysql-proxy/目录中。
|
||||
```
|
||||
--[[ $%BEGINLICENSE%$
|
||||
Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; version 2 of the
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
$%ENDLICENSE%$ --]]
|
||||
|
||||
function set_error(errmsg)
|
||||
proxy.response = {
|
||||
type = proxy.MYSQLD_PACKET_ERR,
|
||||
errmsg = errmsg or "error"
|
||||
}
|
||||
end
|
||||
|
||||
function read_query(packet)
|
||||
if packet:byte() ~= proxy.COM_QUERY then
|
||||
set_error("[admin] we only handle text-based queries (COM_QUERY)")
|
||||
return proxy.PROXY_SEND_RESULT
|
||||
end
|
||||
|
||||
local query = packet:sub(2)
|
||||
|
||||
local rows = { }
|
||||
local fields = { }
|
||||
|
||||
if query:lower() == "select * from backends" then
|
||||
fields = {
|
||||
{ name = "backend_ndx",
|
||||
type = proxy.MYSQL_TYPE_LONG },
|
||||
|
||||
{ name = "address",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
{ name = "state",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
{ name = "type",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
{ name = "uuid",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
{ name = "connected_clients",
|
||||
type = proxy.MYSQL_TYPE_LONG },
|
||||
}
|
||||
|
||||
for i = 1, #proxy.global.backends do
|
||||
local states = {
|
||||
"unknown",
|
||||
"up",
|
||||
"down"
|
||||
}
|
||||
local types = {
|
||||
"unknown",
|
||||
"rw",
|
||||
"ro"
|
||||
}
|
||||
local b = proxy.global.backends[i]
|
||||
|
||||
rows[#rows + 1] = {
|
||||
i,
|
||||
b.dst.name, -- configured backend address
|
||||
states[b.state + 1], -- the C-id is pushed down starting at 0
|
||||
types[b.type + 1], -- the C-id is pushed down starting at 0
|
||||
b.uuid, -- the MySQL Server's UUID if it is managed
|
||||
b.connected_clients -- currently connected clients
|
||||
}
|
||||
end
|
||||
elseif query:lower() == "select * from help" then
|
||||
fields = {
|
||||
{ name = "command",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
{ name = "description",
|
||||
type = proxy.MYSQL_TYPE_STRING },
|
||||
}
|
||||
rows[#rows + 1] = { "SELECT * FROM help", "shows this help" }
|
||||
rows[#rows + 1] = { "SELECT * FROM backends", "lists the backends and their state" }
|
||||
else
|
||||
set_error("use 'SELECT * FROM help' to see the supported commands")
|
||||
return proxy.PROXY_SEND_RESULT
|
||||
end
|
||||
|
||||
proxy.response = {
|
||||
type = proxy.MYSQLD_PACKET_OK,
|
||||
resultset = {
|
||||
fields = fields,
|
||||
rows = rows
|
||||
}
|
||||
}
|
||||
return proxy.PROXY_SEND_RESULT
|
||||
end
|
||||
```
|
||||
|
||||
#### 6、测试
|
||||
|
||||
6.1 管理功能测试
|
||||
```
|
||||
# mysql -uadmin -padmin -h172.16.100.107 --port=4041
|
||||
```
|
||||
```
|
||||
Welcome to the MySQL monitor. Commands end with ; or \g.
|
||||
Your MySQL connection id is 1
|
||||
Server version: 5.0.99-agent-admin
|
||||
|
||||
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
|
||||
|
||||
mysql> SELECT * FROM backends;
|
||||
+-------------+-------------------+-------+------+------+-------------------+
|
||||
| backend_ndx | address | state | type | uuid | connected_clients |
|
||||
+-------------+-------------------+-------+------+------+-------------------+
|
||||
| 1 | 172.16.100.6:3306 | up | rw | NULL | 0 |
|
||||
| 2 | 172.16.100.7:3306 | up | ro | NULL | 0 |
|
||||
+-------------+-------------------+-------+------+------+-------------------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
6.2 读写分离测试
|
||||
```
|
||||
# mysql -uroot -pmagedu.com -h172.16.100.107 --port=4040
|
||||
|
||||
```
|
||||
|
||||
下面的读写分享脚本是由mysql-proxy-0.8.3提供,将其复制保存为/usr/lib/mysql-proxy/lua/proxy/rw-splitting.lua,就可以启动服务了。
|
||||
```
|
||||
--[[ $%BEGINLICENSE%$
|
||||
Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; version 2 of the
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
$%ENDLICENSE%$ --]]
|
||||
|
||||
---
|
||||
-- a flexible statement based load balancer with connection pooling
|
||||
--
|
||||
-- * build a connection pool of min_idle_connections for each backend and maintain
|
||||
-- its size
|
||||
-- *
|
||||
--
|
||||
--
|
||||
|
||||
local commands = require("proxy.commands")
|
||||
local tokenizer = require("proxy.tokenizer")
|
||||
local lb = require("proxy.balance")
|
||||
local auto_config = require("proxy.auto-config")
|
||||
|
||||
--- config
|
||||
--
|
||||
-- connection pool
|
||||
if not proxy.global.config.rwsplit then
|
||||
proxy.global.config.rwsplit = {
|
||||
min_idle_connections = 4,
|
||||
max_idle_connections = 8,
|
||||
|
||||
is_debug = false
|
||||
}
|
||||
end
|
||||
|
||||
---
|
||||
-- read/write splitting sends all non-transactional SELECTs to the slaves
|
||||
--
|
||||
-- is_in_transaction tracks the state of the transactions
|
||||
local is_in_transaction = false
|
||||
|
||||
-- if this was a SELECT SQL_CALC_FOUND_ROWS ... stay on the same connections
|
||||
local is_in_select_calc_found_rows = false
|
||||
|
||||
---
|
||||
-- get a connection to a backend
|
||||
--
|
||||
-- as long as we don't have enough connections in the pool, create new connections
|
||||
--
|
||||
function connect_server()
|
||||
local is_debug = proxy.global.config.rwsplit.is_debug
|
||||
-- make sure that we connect to each backend at least ones to
|
||||
-- keep the connections to the servers alive
|
||||
--
|
||||
-- on read_query we can switch the backends again to another backend
|
||||
|
||||
if is_debug then
|
||||
print()
|
||||
print("[connect_server] " .. proxy.connection.client.src.name)
|
||||
end
|
||||
|
||||
local rw_ndx = 0
|
||||
|
||||
-- init all backends
|
||||
for i = 1, #proxy.global.backends do
|
||||
local s = proxy.global.backends[i]
|
||||
local pool = s.pool -- we don't have a username yet, try to find a connections which is idling
|
||||
local cur_idle = pool.users[""].cur_idle_connections
|
||||
|
||||
pool.min_idle_connections = proxy.global.config.rwsplit.min_idle_connections
|
||||
pool.max_idle_connections = proxy.global.config.rwsplit.max_idle_connections
|
||||
|
||||
if is_debug then
|
||||
print(" [".. i .."].connected_clients = " .. s.connected_clients)
|
||||
print(" [".. i .."].pool.cur_idle = " .. cur_idle)
|
||||
print(" [".. i .."].pool.max_idle = " .. pool.max_idle_connections)
|
||||
print(" [".. i .."].pool.min_idle = " .. pool.min_idle_connections)
|
||||
print(" [".. i .."].type = " .. s.type)
|
||||
print(" [".. i .."].state = " .. s.state)
|
||||
end
|
||||
|
||||
-- prefer connections to the master
|
||||
if s.type == proxy.BACKEND_TYPE_RW and
|
||||
s.state ~= proxy.BACKEND_STATE_DOWN and
|
||||
cur_idle < pool.min_idle_connections then
|
||||
proxy.connection.backend_ndx = i
|
||||
break
|
||||
elseif s.type == proxy.BACKEND_TYPE_RO and
|
||||
s.state ~= proxy.BACKEND_STATE_DOWN and
|
||||
cur_idle < pool.min_idle_connections then
|
||||
proxy.connection.backend_ndx = i
|
||||
break
|
||||
elseif s.type == proxy.BACKEND_TYPE_RW and
|
||||
s.state ~= proxy.BACKEND_STATE_DOWN and
|
||||
rw_ndx == 0 then
|
||||
rw_ndx = i
|
||||
end
|
||||
end
|
||||
|
||||
if proxy.connection.backend_ndx == 0 then
|
||||
if is_debug then
|
||||
print(" [" .. rw_ndx .. "] taking master as default")
|
||||
end
|
||||
proxy.connection.backend_ndx = rw_ndx
|
||||
end
|
||||
|
||||
-- pick a random backend
|
||||
--
|
||||
-- we someone have to skip DOWN backends
|
||||
|
||||
-- ok, did we got a backend ?
|
||||
|
||||
if proxy.connection.server then
|
||||
if is_debug then
|
||||
print(" using pooled connection from: " .. proxy.connection.backend_ndx)
|
||||
end
|
||||
|
||||
-- stay with it
|
||||
return proxy.PROXY_IGNORE_RESULT
|
||||
end
|
||||
|
||||
if is_debug then
|
||||
print(" [" .. proxy.connection.backend_ndx .. "] idle-conns below min-idle")
|
||||
end
|
||||
|
||||
-- open a new connection
|
||||
end
|
||||
|
||||
---
|
||||
-- put the successfully authed connection into the connection pool
|
||||
--
|
||||
-- @param auth the context information for the auth
|
||||
--
|
||||
-- auth.packet is the packet
|
||||
function read_auth_result( auth )
|
||||
if is_debug then
|
||||
print("[read_auth_result] " .. proxy.connection.client.src.name)
|
||||
end
|
||||
if auth.packet:byte() == proxy.MYSQLD_PACKET_OK then
|
||||
-- auth was fine, disconnect from the server
|
||||
proxy.connection.backend_ndx = 0
|
||||
elseif auth.packet:byte() == proxy.MYSQLD_PACKET_EOF then
|
||||
-- we received either a
|
||||
--
|
||||
-- * MYSQLD_PACKET_ERR and the auth failed or
|
||||
-- * MYSQLD_PACKET_EOF which means a OLD PASSWORD (4.0) was sent
|
||||
print("(read_auth_result) ... not ok yet");
|
||||
elseif auth.packet:byte() == proxy.MYSQLD_PACKET_ERR then
|
||||
-- auth failed
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- read/write splitting
|
||||
function read_query( packet )
|
||||
local is_debug = proxy.global.config.rwsplit.is_debug
|
||||
local cmd = commands.parse(packet)
|
||||
local c = proxy.connection.client
|
||||
|
||||
local r = auto_config.handle(cmd)
|
||||
if r then return r end
|
||||
|
||||
local tokens
|
||||
local norm_query
|
||||
|
||||
-- looks like we have to forward this statement to a backend
|
||||
if is_debug then
|
||||
print("[read_query] " .. proxy.connection.client.src.name)
|
||||
print(" current backend = " .. proxy.connection.backend_ndx)
|
||||
print(" client default db = " .. c.default_db)
|
||||
print(" client username = " .. c.username)
|
||||
if cmd.type == proxy.COM_QUERY then
|
||||
print(" query = " .. cmd.query)
|
||||
end
|
||||
end
|
||||
|
||||
if cmd.type == proxy.COM_QUIT then
|
||||
-- don't send COM_QUIT to the backend. We manage the connection
|
||||
-- in all aspects.
|
||||
proxy.response = {
|
||||
type = proxy.MYSQLD_PACKET_OK,
|
||||
}
|
||||
|
||||
if is_debug then
|
||||
print(" (QUIT) current backend = " .. proxy.connection.backend_ndx)
|
||||
end
|
||||
|
||||
return proxy.PROXY_SEND_RESULT
|
||||
end
|
||||
|
||||
-- COM_BINLOG_DUMP packet can't be balanced
|
||||
--
|
||||
-- so we must send it always to the master
|
||||
if cmd.type == proxy.COM_BINLOG_DUMP then
|
||||
-- if we don't have a backend selected, let's pick the master
|
||||
--
|
||||
if proxy.connection.backend_ndx == 0 then
|
||||
proxy.connection.backend_ndx = lb.idle_failsafe_rw()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
proxy.queries:append(1, packet, { resultset_is_needed = true })
|
||||
|
||||
-- read/write splitting
|
||||
--
|
||||
-- send all non-transactional SELECTs to a slave
|
||||
if not is_in_transaction and
|
||||
cmd.type == proxy.COM_QUERY then
|
||||
tokens = tokens or assert(tokenizer.tokenize(cmd.query))
|
||||
|
||||
local stmt = tokenizer.first_stmt_token(tokens)
|
||||
|
||||
if stmt.token_name == "TK_SQL_SELECT" then
|
||||
is_in_select_calc_found_rows = false
|
||||
local is_insert_id = false
|
||||
|
||||
for i = 1, #tokens do
|
||||
local token = tokens[i]
|
||||
-- SQL_CALC_FOUND_ROWS + FOUND_ROWS() have to be executed
|
||||
-- on the same connection
|
||||
-- print("token: " .. token.token_name)
|
||||
-- print(" val: " .. token.text)
|
||||
|
||||
if not is_in_select_calc_found_rows and token.token_name == "TK_SQL_SQL_CALC_FOUND_ROWS" then
|
||||
is_in_select_calc_found_rows = true
|
||||
elseif not is_insert_id and token.token_name == "TK_LITERAL" then
|
||||
local utext = token.text:upper()
|
||||
|
||||
if utext == "LAST_INSERT_ID" or
|
||||
utext == "@@INSERT_ID" then
|
||||
is_insert_id = true
|
||||
end
|
||||
end
|
||||
|
||||
-- we found the two special token, we can't find more
|
||||
if is_insert_id and is_in_select_calc_found_rows then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- if we ask for the last-insert-id we have to ask it on the original
|
||||
-- connection
|
||||
if not is_insert_id then
|
||||
local backend_ndx = lb.idle_ro()
|
||||
|
||||
if backend_ndx > 0 then
|
||||
proxy.connection.backend_ndx = backend_ndx
|
||||
end
|
||||
else
|
||||
print(" found a SELECT LAST_INSERT_ID(), staying on the same backend")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- no backend selected yet, pick a master
|
||||
if proxy.connection.backend_ndx == 0 then
|
||||
-- we don't have a backend right now
|
||||
--
|
||||
-- let's pick a master as a good default
|
||||
--
|
||||
proxy.connection.backend_ndx = lb.idle_failsafe_rw()
|
||||
end
|
||||
|
||||
-- by now we should have a backend
|
||||
--
|
||||
-- in case the master is down, we have to close the client connections
|
||||
-- otherwise we can go on
|
||||
if proxy.connection.backend_ndx == 0 then
|
||||
return proxy.PROXY_SEND_QUERY
|
||||
end
|
||||
|
||||
local s = proxy.connection.server
|
||||
|
||||
-- if client and server db don't match, adjust the server-side
|
||||
--
|
||||
-- skip it if we send a INIT_DB anyway
|
||||
if cmd.type ~= proxy.COM_INIT_DB and
|
||||
c.default_db and c.default_db ~= s.default_db then
|
||||
print(" server default db: " .. s.default_db)
|
||||
print(" client default db: " .. c.default_db)
|
||||
print(" syncronizing")
|
||||
proxy.queries:prepend(2, string.char(proxy.COM_INIT_DB) .. c.default_db, { resultset_is_needed = true })
|
||||
end
|
||||
|
||||
-- send to master
|
||||
if is_debug then
|
||||
if proxy.connection.backend_ndx > 0 then
|
||||
local b = proxy.global.backends[proxy.connection.backend_ndx]
|
||||
print(" sending to backend : " .. b.dst.name);
|
||||
print(" is_slave : " .. tostring(b.type == proxy.BACKEND_TYPE_RO));
|
||||
print(" server default db: " .. s.default_db)
|
||||
print(" server username : " .. s.username)
|
||||
end
|
||||
print(" in_trans : " .. tostring(is_in_transaction))
|
||||
print(" in_calc_found : " .. tostring(is_in_select_calc_found_rows))
|
||||
print(" COM_QUERY : " .. tostring(cmd.type == proxy.COM_QUERY))
|
||||
end
|
||||
|
||||
return proxy.PROXY_SEND_QUERY
|
||||
end
|
||||
|
||||
---
|
||||
-- as long as we are in a transaction keep the connection
|
||||
-- otherwise release it so another client can use it
|
||||
function read_query_result( inj )
|
||||
local is_debug = proxy.global.config.rwsplit.is_debug
|
||||
local res = assert(inj.resultset)
|
||||
local flags = res.flags
|
||||
|
||||
if inj.id ~= 1 then
|
||||
-- ignore the result of the USE <default_db>
|
||||
-- the DB might not exist on the backend, what do do ?
|
||||
--
|
||||
if inj.id == 2 then
|
||||
-- the injected INIT_DB failed as the slave doesn't have this DB
|
||||
-- or doesn't have permissions to read from it
|
||||
if res.query_status == proxy.MYSQLD_PACKET_ERR then
|
||||
proxy.queries:reset()
|
||||
|
||||
proxy.response = {
|
||||
type = proxy.MYSQLD_PACKET_ERR,
|
||||
errmsg = "can't change DB ".. proxy.connection.client.default_db ..
|
||||
" to on slave " .. proxy.global.backends[proxy.connection.backend_ndx].dst.name
|
||||
}
|
||||
|
||||
return proxy.PROXY_SEND_RESULT
|
||||
end
|
||||
end
|
||||
return proxy.PROXY_IGNORE_RESULT
|
||||
end
|
||||
|
||||
is_in_transaction = flags.in_trans
|
||||
local have_last_insert_id = (res.insert_id and (res.insert_id > 0))
|
||||
|
||||
if not is_in_transaction and
|
||||
not is_in_select_calc_found_rows and
|
||||
not have_last_insert_id then
|
||||
-- release the backend
|
||||
proxy.connection.backend_ndx = 0
|
||||
elseif is_debug then
|
||||
print("(read_query_result) staying on the same backend")
|
||||
print(" in_trans : " .. tostring(is_in_transaction))
|
||||
print(" in_calc_found : " .. tostring(is_in_select_calc_found_rows))
|
||||
print(" have_insert_id : " .. tostring(have_last_insert_id))
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- close the connections if we have enough connections in the pool
|
||||
--
|
||||
-- @return nil - close connection
|
||||
-- IGNORE_RESULT - store connection in the pool
|
||||
function disconnect_client()
|
||||
local is_debug = proxy.global.config.rwsplit.is_debug
|
||||
if is_debug then
|
||||
print("[disconnect_client] " .. proxy.connection.client.src.name)
|
||||
end
|
||||
|
||||
-- make sure we are disconnection from the connection
|
||||
-- to move the connection into the pool
|
||||
proxy.connection.backend_ndx = 0
|
||||
end
|
||||
```
|
||||
|
||||
|
7
数据库/mysql/Mysql四种隔离级别.md
Normal file
7
数据库/mysql/Mysql四种隔离级别.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
|
||||
|
||||
Repeatable read (可重复读):可避免脏读、不可重复读的发生。
|
||||
|
||||
Read committed (读已提交):可避免脏读的发生。
|
||||
|
||||
Read uncommitted (读未提交):最低级别,任何情况都无法保证
|
20
数据库/mysql/Mysql处理死锁.md
Normal file
20
数据库/mysql/Mysql处理死锁.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
### 查看数据库的隔离级别
|
||||
```
|
||||
mysql> select @@tx_isolation;
|
||||
```
|
||||
|
||||
### 去查看先当前库的线程情况
|
||||
```
|
||||
mysql> show processlist;
|
||||
```
|
||||
没有看到正在执行的慢SQL记录线程,再去查看innodb的事务表INNODB_TRX,看下里面是否有正在锁定的事务线程,看看ID是否在show full processlist里面的sleep线程中,如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了,我们需要手动kill掉。
|
||||
|
||||
```
|
||||
mysql> SELECT * FROM information_schema.INNODB_TRX;
|
||||
```
|
||||
如果有记录,则找到trx_mysql_thread_id这个字段对应的id, 将其kill掉。假如id=100
|
||||
```
|
||||
mysql->kill 100
|
||||
|
||||
SELECT CONCAT_WS('','kill',' ',t.trx_mysql_thread_id,';')a FROM information_schema.INNODB_TRX t;
|
||||
```
|
37
数据库/mysql/Mysql引擎及特性.md
Normal file
37
数据库/mysql/Mysql引擎及特性.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
### InnoDB
|
||||
```
|
||||
InnoDB是一个事务型的存储引擎,有行级锁定和外键约束
|
||||
Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别,关于数据库事务与其隔离级别的内容请见数据库事务与其隔离级别这类型的文章。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。
|
||||
```
|
||||
#### 适用场景
|
||||
```
|
||||
1)经常更新的表,适合处理多重并发的更新请求。
|
||||
2)支持事务。
|
||||
3)可以从灾难中恢复(通过bin-log日志等)。
|
||||
4)外键约束。只有他支持外键。
|
||||
5)支持自动增加列属性auto_increment。
|
||||
```
|
||||
#### 其他
|
||||
```
|
||||
1)InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。
|
||||
2)InnoDB锁定在行级并且也在SELECT语句提供一个Oracle风格一致的非锁定读,这些特色增加了多用户部署和性能。没有在InnoDB中扩大锁定的需要,因为在InnoDB中行级锁定适合非常小的空间。
|
||||
3)InnoDB也支持FOREIGN KEY强制。在SQL查询中,你可以自由地将InnoDB类型的表与其它MySQL的表的类型混合起来,甚至在同一个查询中也可以混合。
|
||||
4)InnoDB是为处理巨大数据量时的最大性能设计,它的CPU效率可能是任何其它基于磁盘的关系数据库引擎所不能匹敌的。
|
||||
5)InnoDB被用来在众多需要高性能的大型数据库站点上产生。
|
||||
```
|
||||
|
||||
### MyISAM
|
||||
```
|
||||
MyIASM是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。
|
||||
MyIsam 存储引擎独立于操作系统,也就是可以在windows上使用,也可以比较简单的将数据转移到linux操作系统上去。
|
||||
意味着:引擎在创建表的时候,会创建三个文件,一个是.frm文件用于存储表的定义,一个是.MYD文件用于存储表的数据,另一个是.MYI文件,存储的是索引。操作系统对大文件的操作是比较慢的,这样将表分为三个文件,那么.MYD这个文件单独来存放数据自然可以优化数据库的查询等操作。有索引管理和字段管理。MyISAM还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的空间。
|
||||
```
|
||||
#### 适用场景
|
||||
```
|
||||
1)不支持事务的设计,但是并不代表着有事务操作的项目不能用MyIsam存储引擎,可以在service层进行根据自己的业务需求进行相应的控制。
|
||||
2)不支持外键的表设计。
|
||||
3)查询速度很快,如果数据库insert和update的操作比较多的话比较适用。
|
||||
4)整天 对表进行加锁的场景。
|
||||
5)MyISAM极度强调快速读取操作。
|
||||
6)MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。
|
||||
```
|
186
数据库/mysql/Xtrabackup备份mysql
Normal file
186
数据库/mysql/Xtrabackup备份mysql
Normal file
|
@ -0,0 +1,186 @@
|
|||
|
||||
|
||||
使用Xtrabackup进行MySQL备份:
|
||||
|
||||
一、安装
|
||||
|
||||
1、简介
|
||||
Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具。特点:
|
||||
(1)备份过程快速、可靠;
|
||||
(2)备份过程不会打断正在执行的事务;
|
||||
(3)能够基于压缩等功能节约磁盘空间和流量;
|
||||
(4)自动实现备份检验;
|
||||
(5)还原速度快;
|
||||
|
||||
2、安装
|
||||
其最新版的软件可从 http://www.percona.com/software/percona-xtrabackup/ 获得。本文基于RHEL5.8的系统,因此,直接下载相应版本的rpm包安装即可,这里不再演示其过程。
|
||||
|
||||
二、备份的实现
|
||||
|
||||
1、完全备份
|
||||
|
||||
# innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
|
||||
|
||||
如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:
|
||||
mysql> CREATE USER ’bkpuser’@’localhost’ IDENTIFIED BY ’s3cret’;
|
||||
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM ’bkpuser’;
|
||||
mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO ’bkpuser’@’localhost’;
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
|
||||
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命令的目录中。
|
||||
|
||||
在备份的同时,innobackupex还会在备份目录中创建如下文件:
|
||||
(1)xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
|
||||
|
||||
每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
|
||||
|
||||
(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
|
||||
|
||||
(3)xtrabackup_binlog_pos_innodb —— 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。
|
||||
|
||||
(4)xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件;
|
||||
|
||||
(5)backup-my.cnf —— 备份命令用到的配置选项信息;
|
||||
|
||||
在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。
|
||||
|
||||
2、准备(prepare)一个完全备份
|
||||
|
||||
一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。
|
||||
|
||||
innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:
|
||||
|
||||
# innobackupex --apply-log /path/to/BACKUP-DIR
|
||||
如果执行正确,其最后输出的几行信息通常如下:
|
||||
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
|
||||
120407 9:01:36 InnoDB: Starting shutdown...
|
||||
120407 9:01:40 InnoDB: Shutdown completed; log sequence number 92036620
|
||||
120407 09:01:40 innobackupex: completed OK!
|
||||
|
||||
在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。
|
||||
|
||||
|
||||
3、从一个完全备份中恢复数据
|
||||
|
||||
注意:恢复不用启动MySQL
|
||||
|
||||
innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。
|
||||
|
||||
# innobackupex --copy-back /path/to/BACKUP-DIR
|
||||
如果执行正确,其输出信息的最后几行通常如下:
|
||||
innobackupex: Starting to copy InnoDB log files
|
||||
innobackupex: in '/backup/2012-04-07_08-17-03'
|
||||
innobackupex: back to original InnoDB log directory '/mydata/data'
|
||||
innobackupex: Finished copying back files.
|
||||
|
||||
120407 09:36:10 innobackupex: completed OK!
|
||||
|
||||
请确保如上信息的最行一行出现“innobackupex: completed OK!”。
|
||||
|
||||
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:
|
||||
|
||||
# chown -R mysql:mysql /mydata/data/
|
||||
|
||||
|
||||
4、使用innobackupex进行增量备份
|
||||
|
||||
每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。
|
||||
|
||||
要实现第一次增量备份,可以使用下面的命令进行:
|
||||
|
||||
# innobackupex --incremental /backup --incremental-basedir=BASEDIR
|
||||
|
||||
其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。
|
||||
|
||||
需要注意的是,增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。
|
||||
|
||||
“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:
|
||||
(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。
|
||||
(2)基于所有的备份将未提交的事务进行“回滚”。
|
||||
|
||||
于是,操作就变成了:
|
||||
# innobackupex --apply-log --redo-only BASE-DIR
|
||||
|
||||
接着执行:
|
||||
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1
|
||||
|
||||
而后是第二个增量:
|
||||
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2
|
||||
|
||||
其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作;
|
||||
|
||||
5、Xtrabackup的“流”及“备份压缩”功能
|
||||
|
||||
Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用--stream选项即可。如:
|
||||
|
||||
# innobackupex --stream=tar /backup | gzip > /backup/`date +%F_%H-%M-%S`.tar.gz
|
||||
|
||||
甚至也可以使用类似如下命令将数据备份至其它服务器:
|
||||
# innobackupex --stream=tar /backup | ssh user@www.magedu.com "cat - > /backups/`date +%F_%H-%M-%S`.tar"
|
||||
|
||||
此外,在执行本地备份时,还可以使用--parallel选项对多个文件进行并行复制。此选项用于指定在复制时启动的线程数目。当然,在实际进行备份时要利用此功能的便利性,也需要启用innodb_file_per_table选项或共享的表空间通过innodb_data_file_path选项存储在多个ibdata文件中。对某一数据库的多个文件的复制无法利用到此功能。其简单使用方法如下:
|
||||
# innobackupex --parallel /path/to/backup
|
||||
|
||||
同时,innobackupex备份的数据文件也可以存储至远程主机,这可以使用--remote-host选项来实现:
|
||||
# innobackupex --remote-host=root@www.magedu.com /path/IN/REMOTE/HOST/to/backup
|
||||
|
||||
|
||||
|
||||
6、导入或导出单张表
|
||||
|
||||
默认情况下,InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植,即便使用了innodb_file_per_table选项。而使用Xtrabackup工具可以实现此种功能,不过,此时需要“导出”表的mysql服务器启用了innodb_file_per_table选项(严格来说,是要“导出”的表在其创建之前,mysql服务器就启用了innodb_file_per_table选项),并且“导入”表的服务器同时启用了innodb_file_per_table和innodb_expand_import选项。
|
||||
|
||||
(1)“导出”表
|
||||
导出表是在备份的prepare阶段进行的,因此,一旦完全备份完成,就可以在prepare过程中通过--export选项将某表导出了:
|
||||
# innobackupex --apply-log --export /path/to/backup
|
||||
|
||||
此命令会为每个innodb表的表空间创建一个以.exp结尾的文件,这些以.exp结尾的文件则可以用于导入至其它服务器。
|
||||
|
||||
(2)“导入”表
|
||||
要在mysql服务器上导入来自于其它服务器的某innodb表,需要先在当前服务器上创建一个跟原表表结构一致的表,而后才能实现将表导入:
|
||||
mysql> CREATE TABLE mytable (...) ENGINE=InnoDB;
|
||||
|
||||
然后将此表的表空间删除:
|
||||
mysql> ALTER TABLE mydatabase.mytable DISCARD TABLESPACE;
|
||||
|
||||
接下来,将来自于“导出”表的服务器的mytable表的mytable.ibd和mytable.exp文件复制到当前服务器的数据目录,然后使用如下命令将其“导入”:
|
||||
mysql> ALTER TABLE mydatabase.mytable IMPORT TABLESPACE;
|
||||
|
||||
|
||||
|
||||
|
||||
7、使用Xtrabackup对数据库进行部分备份
|
||||
|
||||
Xtrabackup也可以实现部分备份,即只备份某个或某些指定的数据库或某数据库中的某个或某些表。但要使用此功能,必须启用innodb_file_per_table选项,即每张表保存为一个独立的文件。同时,其也不支持--stream选项,即不支持将数据通过管道传输给其它程序进行处理。
|
||||
|
||||
此外,还原部分备份跟还原全部数据的备份也有所不同,即你不能通过简单地将prepared的部分备份使用--copy-back选项直接复制回数据目录,而是要通过导入表的方向来实现还原。当然,有些情况下,部分备份也可以直接通过--copy-back进行还原,但这种方式还原而来的数据多数会产生数据不一致的问题,因此,无论如何不推荐使用这种方式。
|
||||
|
||||
(1)创建部分备份
|
||||
|
||||
创建部分备份的方式有三种:正则表达式(--include), 枚举表文件(--tables-file)和列出要备份的数据库(--databases)。
|
||||
|
||||
(a)使用--include
|
||||
使用--include时,要求为其指定要备份的表的完整名称,即形如databasename.tablename,如:
|
||||
# innobackupex --include='^mageedu[.]tb1' /path/to/backup
|
||||
|
||||
(b)使用--tables-file
|
||||
此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称;如:
|
||||
# echo -e 'mageedu.tb1\nmageedu.tb2' > /tmp/tables.txt
|
||||
# innobackupex --tables-file=/tmp/tables.txt /path/to/backup
|
||||
|
||||
(c)使用--databases
|
||||
此选项接受的参数为数据名,如果要指定多个数据库,彼此间需要以空格隔开;同时,在指定某数据库时,也可以只指定其中的某张表。此外,此选项也可以接受一个文件为参数,文件中每一行为一个要备份的对象。如:
|
||||
# innobackupex --databases="mageedu testdb" /path/to/backup
|
||||
|
||||
(2)整理(preparing)部分备份
|
||||
prepare部分备份的过程类似于导出表的过程,要使用--export选项进行:
|
||||
# innobackupex --apply-log --export /pat/to/partial/backup
|
||||
|
||||
此命令执行过程中,innobackupex会调用xtrabackup命令从数据字典中移除缺失的表,因此,会显示出许多关于“表不存在”类的警告信息。同时,也会显示出为备份文件中存在的表创建.exp文件的相关信息。
|
||||
|
||||
(3)还原部分备份
|
||||
还原部分备份的过程跟导入表的过程相同。当然,也可以通过直接复制prepared状态的备份直接至数据目录中实现还原,不要此时要求数据目录处于一致状态。
|
||||
|
||||
|
||||
|
||||
|
165
数据库/mysql/mysql.html
Normal file
165
数据库/mysql/mysql.html
Normal file
|
@ -0,0 +1,165 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="tool" content="leanote-desktop-app">
|
||||
<title>mysql</title>
|
||||
<style>
|
||||
|
||||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*公用文字样式*/
|
||||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||||
.note-container{
|
||||
width:850px;
|
||||
margin:auto;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 1px 1px 10px #eee;
|
||||
}
|
||||
#title {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin-bottom: 16px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: none;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
table tr:nth-child(2n) {
|
||||
background-color: rgb(247, 247, 249);
|
||||
}
|
||||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||||
border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
blockquote {
|
||||
border-left-width:10px;
|
||||
background-color:rgba(128,128,128,0.05);
|
||||
border-top-right-radius:5px;
|
||||
border-bottom-right-radius:5px;
|
||||
padding:15px 20px;
|
||||
border-left:5px solid rgba(128,128,128,0.075);
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom:1.1em;
|
||||
font-size:1em;
|
||||
line-height:1.45
|
||||
}
|
||||
blockquote ul:last-child,blockquote ol:last-child {
|
||||
margin-bottom:0
|
||||
}
|
||||
pre {
|
||||
padding: 18px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
font-size: 90%;
|
||||
color: #c7254e;
|
||||
white-space: nowrap;
|
||||
background-color: #f9f2f4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footnote {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
pre {
|
||||
word-break:break-word
|
||||
}
|
||||
p,pre,pre.prettyprint,blockquote {
|
||||
margin:0 0 1.1em
|
||||
}
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
.sequence-diagram,.flow-chart {
|
||||
text-align:center;
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
.sequence-diagram text,.flow-chart text {
|
||||
font-size:15px !important;
|
||||
font-family:"Source Sans Pro",sans-serif !important
|
||||
}
|
||||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||||
fill:#f6f6f6
|
||||
}
|
||||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||||
stroke:#3f3f3f
|
||||
}
|
||||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||||
stroke:none
|
||||
}
|
||||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||||
fill:#3f3f3f
|
||||
}
|
||||
ul,ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
ul ul,ol ul,ul ol,ol ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
kbd {
|
||||
padding:.1em .6em;
|
||||
border:1px solid rgba(63,63,63,0.25);
|
||||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
font-size:.7em;
|
||||
font-family:sans-serif;
|
||||
background-color:#fff;
|
||||
color:#333;
|
||||
border-radius:3px;
|
||||
display:inline-block;
|
||||
margin:0 .1em;
|
||||
white-space:nowrap
|
||||
}
|
||||
.toc ul {
|
||||
list-style-type:none;
|
||||
margin-bottom:15px
|
||||
}
|
||||
</style>
|
||||
<!-- 该css供自定义样式 -->
|
||||
<link href="../leanote-html.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="note-container">
|
||||
<h1 class="title" id="leanote-title">mysql</h1>
|
||||
<div class="content-html" id="leanote-content"><div>grant</div><div>show grants for "username"@"host"</div><div><br></div><div>flush privileges;</div><div><div>用mysqldump工具导出表数据</div><div>mysqldump -uiboxpaynew -p -h172.16.1.86 -t --compact iboxpay sp_posts >/tmp/sp_posts.sql</div></div><div>//-u用户,-p密码,-h主机,-t表数据,--compact去掉注释,iboxpay数据库,sp_posts表,-d表结构</div><div><br></div><div><br></div><div>备库同步</div><div><div>mysql -e "show databases;" -uroot -p'password' | grep -Ev "Database|information_schema|mysql|sys|performance_schema|test"| xargs mysqldump -uroot -p'password' --databases -R> /tmp/aaa.sql</div><p><br></p></div></div>
|
||||
</div>
|
||||
|
||||
<!-- 该js供其它处理 -->
|
||||
<script src="../leanote-html.js"></script>
|
||||
</body>
|
||||
</html>
|
29
数据库/mysql/mysqladmin使用方法
Normal file
29
数据库/mysql/mysqladmin使用方法
Normal file
|
@ -0,0 +1,29 @@
|
|||
mysqladmin工具
|
||||
mysqladmin [options] command [arg] [command[arg]] .....
|
||||
|
||||
command
|
||||
create DB_Name 创建空数据库
|
||||
-e:直接返回
|
||||
drop DB_Name 删除数据库
|
||||
debug 打开调试日志并记录与error log中
|
||||
status:输出简要状态信息
|
||||
-sleep # 指定显示延迟
|
||||
-count # 指定批次
|
||||
extended-status:输出mysq的各状态变量及数值,相当于执行“mysql> show global status”
|
||||
flush-hosts:清空主机相关的缓存:DNS解析缓存,此前因为连接错误次数过多而被拒绝访问mysqld的主机列表
|
||||
flush-logs:日志滚动,主要是二进制日志和中继日志
|
||||
refresh:相当于同时使用flush-logs和flush-hosts
|
||||
|
||||
flush-privileges:通知服务器重读授权表
|
||||
reload:重载授权表
|
||||
flush-status:重置状态变量的值
|
||||
flush-tables:关闭当前打开的表文件句柄
|
||||
flush-threads:清空线程缓存
|
||||
kill:杀死指定的线程,可以一次杀死多个线程,以逗号分隔,但不能有多余空格
|
||||
password:修改指定用户的密码
|
||||
processlist: 线程列表
|
||||
shutdown:关闭mysqld进程
|
||||
|
||||
start-slave 启动从服务器进程
|
||||
stop-slave 关闭从服务器进程
|
||||
variables:显示mysql的各服务器进程
|
48
数据库/mysql/mysql主主复制
Normal file
48
数据库/mysql/mysql主主复制
Normal file
|
@ -0,0 +1,48 @@
|
|||
1)、在两台服务器上各自建立一个具有复制权限的用户;
|
||||
2)、修改配置文件:
|
||||
# 主服务器A上
|
||||
[mysqld]
|
||||
server-id = 10
|
||||
log-bin = mysql-bin
|
||||
relay-log = relay-mysql
|
||||
auto-increment-offset = 2
|
||||
auto-increment-increment = 1
|
||||
|
||||
|
||||
# 主服务器B上
|
||||
[mysqld]
|
||||
server-id = 20
|
||||
log-bin = mysql-bin
|
||||
relay-log = relay-mysql
|
||||
auto-increment-increment = 2 # 起始值
|
||||
auto-increment-offset = 2 # 步长
|
||||
|
||||
|
||||
3)、如果此时两台服务器均为新建立,且无其它写入操作,各服务器只需记录当前自己二进制日志文件及事件位置,以之作为另外的服务器复制起始位置即可
|
||||
|
||||
serverA|mysql> SHOW MASTER STATUS\G
|
||||
************************** 1. row ***************************
|
||||
File: mysql-bin.000001
|
||||
Position: 710
|
||||
Binlog_Do_DB:
|
||||
Binlog_Ignore_DB:
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
server2|mysql> SHOW MASTER STATUS\G
|
||||
mysql> SHOW MASTER STATUS\G
|
||||
*************************** 1. row ***************************
|
||||
File: mysql-bin.000003
|
||||
Position: 811
|
||||
Binlog_Do_DB:
|
||||
Binlog_Ignore_DB:
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
4、各服务器接下来指定对另一台服务器为自己的主服务器即可:
|
||||
serverA|mysql> CHANGE MASTER TO ...,MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=811
|
||||
|
||||
serverB|mysql> CHANGE MASTER TO ...,MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=710
|
||||
|
||||
|
||||
多主,且高可用的解决方案:
|
||||
MMM:Multi Master MySQL
|
||||
MHA:MySQL HA
|
16
数据库/mysql/mysql二进制日志相关
Normal file
16
数据库/mysql/mysql二进制日志相关
Normal file
|
@ -0,0 +1,16 @@
|
|||
二进制文件的字段说明
|
||||
1、事件发生的日期和时间
|
||||
2、服务器id
|
||||
3、时间结束位置
|
||||
4、事件类型
|
||||
5、原服务器生成此事件时的线程id(查看线程 [交互]show processlist)
|
||||
6、语句的时间戳和写入二进制文件的时间差
|
||||
7、错误代码
|
||||
8、事件内容
|
||||
9、时间位置,相当于下一个事件
|
||||
|
||||
查看二进制文件 mysqlbinlog binlogfile
|
||||
查看日志偏移点 [交互]show master status;
|
||||
二进制日志滚动 [交互]flush logs;
|
||||
查看从指定偏移开始的日志 mysqlbinlog --start-position=偏移量 binlogfile
|
||||
查看指定事件的日志 [交互]show binlog events in logfile
|
5
数据库/mysql/mysql优化相关
Normal file
5
数据库/mysql/mysql优化相关
Normal file
|
@ -0,0 +1,5 @@
|
|||
1、删除所有匿名用户 drop user ''@'localhost';
|
||||
2、为所有root用户设定密码
|
||||
[交互]set password for username@hosr = password('密码');
|
||||
[交互]update mysql.user set password = password('密码') where user = 'root'; flush privileges;
|
||||
mysqladmin -uusername -hhost password '密码' -p; mysqladmin -uusername -hhost -p flush-privileges
|
56
数据库/mysql/mysql基础
Normal file
56
数据库/mysql/mysql基础
Normal file
|
@ -0,0 +1,56 @@
|
|||
%:匹配任意长度任意字符
|
||||
_:匹配任意单个字符
|
||||
/*...*/:注释
|
||||
|
||||
数据库支持的所有服务器选项列表 mysqld --help --verbose
|
||||
1、显示musqld使用配置文件的方式
|
||||
2、显示mysqld启动时可用的选项,通常为长选项
|
||||
3、显示mysqld的配置文件中可用的配置变量
|
||||
|
||||
# 可以使用like子句
|
||||
数据库变量 [交互]show variables;
|
||||
数据库全局变量 [交互]show global variables;
|
||||
数据库会话变量 [交互]show session variables;
|
||||
数据库某个变量 [交互]select @@[global|session].variables_name;
|
||||
查看全局变量 [交互]select * from information_schema.GLOBAL_VARIABLES where VARIABLE_NAME='SOME_VARIABLE_NAME';
|
||||
查看会话变量 [交互]select * from information_schema.SESSION_VARIABLES where VARIABLE_NAME='SOME_VARIABLE_NAME';
|
||||
|
||||
|
||||
修改变量值 [交互]set [global|session] variables_name="值"
|
||||
|
||||
数据库状态 [交互]show status;
|
||||
数据库全局状态 [交互]show global status;
|
||||
数据库状态 [交互]show session status;
|
||||
|
||||
|
||||
查看数据库支持的引擎及引擎特性 [交互]show engines;
|
||||
|
||||
|
||||
[交互]help contents 所有支持的帮助信息
|
||||
[交互]help 关键字 获取特定的帮助信息
|
||||
|
||||
[交互]\. /path/to/sqlscript 执行sql脚本
|
||||
[交互]\q 退出
|
||||
[交互]\? help
|
||||
[交互]\c 中断输入
|
||||
[交互]\g 语句分隔符(无论是否是;)
|
||||
[交互]\G 以行形式显示执行结果
|
||||
[交互]\! 执行shell命令
|
||||
[交互]\s status
|
||||
|
||||
|
||||
快捷键
|
||||
ctrl+w:删除光标前的单词
|
||||
ctrl+u:删除光标之前的所有字符
|
||||
ctrl+y:粘贴之前删除的内容
|
||||
ctrl+a:移动光标到行首
|
||||
ctrl+e:移动光标到行尾
|
||||
|
||||
|
||||
mysql客户端连接进入服务器
|
||||
-e sql:不登陆数据库显示sql执行内容
|
||||
--compress 压缩
|
||||
-H或--html:结果显示为html
|
||||
-X或--xml:结果显示xml
|
||||
--safe-update:拒绝使用无where子句的update或delete语句
|
||||
|
248
数据库/mysql/mysql增删改查说明
Normal file
248
数据库/mysql/mysql增删改查说明
Normal file
|
@ -0,0 +1,248 @@
|
|||
MySQL有内置的SQL模型SQL_MODE:用来定义字符超出的操作和模仿别的数据库的类型,通过修改全局变量
|
||||
常用的模式有:
|
||||
TRADITIONAL 使用传统模式
|
||||
STRICT_TRANS_TABLES 仅对支持事务的表的严格模式
|
||||
STRICT_ALL_TABLES 对所有表使用严格模式
|
||||
|
||||
设定服务器变量的值:通常仅用于支持动态的变量
|
||||
支持修改的服务器变量
|
||||
动态变量:可以在MySQL运行时修改
|
||||
静态变量:与配置文件中修改其值,并重启后方能生效
|
||||
服务器变量从其生效范围来讲,分两类
|
||||
全局变量:服务器级别,修改之后仅对新建立的会话生效
|
||||
回话变量:会话级别,仅对当前会话有效
|
||||
会话建立时,从全局继承各变量
|
||||
查看服务器变量
|
||||
mysql> show [{global|session}] variables [like ''];
|
||||
mysql> select @@{globa|session}.variable_name
|
||||
mysql> mysql> select * from information_schema.GLOBAL_VARIABLES where VARIABLE_NAME='SOME_VARIABLE_NAME'; 查看全局变量
|
||||
mysql> mysql> select * from information_schema.SESSION_VARIABLES where VARIABLE_NAME='SOME_VARIABLE_NAME'; 查看会话变量
|
||||
|
||||
修改变量:
|
||||
前提:默认仅管理员有权限修改全局变量
|
||||
mysql> set {global|session} variable_name='value';
|
||||
注意:无论是全局还是会话级别的动态变量修改,在重启mysql后都会失效,想永久有效,可以定义在配置文件中的响应段中[mysqld]
|
||||
|
||||
|
||||
数据库:
|
||||
创建数据库
|
||||
create database
|
||||
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
|
||||
[[DEFAULT] CHARACTER SET [=] charset_name 字符集
|
||||
| [DEFAULT] COLLATE [=] collation_name 排序方式]
|
||||
删除数据库
|
||||
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
|
||||
修改数据库的字符集和排序字符以及数据字典
|
||||
ALTER {DATABASE | SCHEMA} [db_name]
|
||||
[[DEFAULT] CHARACTER SET [=] charset_name 字符集
|
||||
| [DEFAULT] COLLATE [=] collation_name 排序方式]
|
||||
ALTER {DATABASE | SCHEMA} db_name
|
||||
UPGRADE DATA DIRECTORY NAME
|
||||
表:
|
||||
创建表:第一种方式
|
||||
CREATE [TEMPORARY(临时表,保存在内存中)] TABLE [IF NOT EXISTS] tbl_name
|
||||
(create_definition,...)
|
||||
[table_options]
|
||||
|
||||
(create_definition,...)
|
||||
字段的定义:字段名、类型和类型修饰符
|
||||
键、索引和约束
|
||||
primary key,unique key,foreign key,check
|
||||
{index|key}
|
||||
[table_options]
|
||||
engine [=] engine_name
|
||||
AUTO_INCREMENT [=] value 指定AUTO_INCREMENT的起始值
|
||||
[DEFAULT] CHARACTER SET [=] charset_name 指定默认字符集
|
||||
CHECKSUM [=] {0 | 1} 是否使用校验值
|
||||
[DEFAULT] COLLATE [=] collation_name 排序规则
|
||||
COMMENT [=] 'string' 注释
|
||||
DELAY_KEY_WRITE [=] {0 | 1} 是否启用键延迟写入
|
||||
ROW_FORMAT [=] {DEFAULT(默认)|DYNAMIC(动态)|FIXED(静态)|COMPRESSED(压缩)|REDUNDANT(冗余)|COMPACT(紧致)} 表格式
|
||||
TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}] 表空间
|
||||
|
||||
myISAM引擎,每表有三个文件,都位于数据库目录
|
||||
tb_name.frm:表结构定义
|
||||
tb_name.MYD:数据文件
|
||||
tb_name.MYI:索引文件
|
||||
|
||||
InnoDB表,有两种存储方式
|
||||
1、默认,每表有一个独立文件和一个多表共享的文件
|
||||
tb_name.frm:表结构的定义,位于数据库目录中
|
||||
ibdata#:共享的表空间文件,默认位于数据目录(datadir指向的目录中)
|
||||
2、独立的表空间
|
||||
tb_name.frm每表有一个表结构文件
|
||||
tb_name.ibd:一个独有的表空间文件
|
||||
应该修改innodb_file_per_table为ON
|
||||
|
||||
表创建:第二种方式(复制表数据)
|
||||
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
|
||||
[(create_definition,...)]
|
||||
[table_options]
|
||||
select_statement
|
||||
|
||||
表创建:第三种方式(复制表结构)
|
||||
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
|
||||
{ LIKE old_tbl_name | (LIKE old_tbl_name) }
|
||||
|
||||
查看表的状态信息
|
||||
show table status like ‘table_name’
|
||||
|
||||
删除表
|
||||
DROP [TEMPORARY] TABLE [IF EXISTS]
|
||||
tbl_name [, tbl_name] ...
|
||||
[RESTRICT | CASCADE]
|
||||
|
||||
修改表:
|
||||
ALTER TABLE tbl_name
|
||||
[alter_specification [, alter_specification] ...]
|
||||
修改字段定义:
|
||||
插入新字段:
|
||||
ADD [COLUMN] col_name column_definition
|
||||
[FIRST | AFTER col_name ]
|
||||
删除字段
|
||||
DROP [COLUMN] col_name
|
||||
修改字段
|
||||
修改字段名称
|
||||
CHANGE [COLUMN] old_col_name new_col_name column_definition
|
||||
[FIRST|AFTER col_name]
|
||||
修改字段类型及属性等
|
||||
MODIFY [COLUMN] col_name column_definition
|
||||
[FIRST | AFTER col_name]
|
||||
表改名:
|
||||
rename to|as new tb_name
|
||||
修改存储引擎
|
||||
engine =
|
||||
指定排序标准的字段
|
||||
ORDER BY col_name [, col_name] ...
|
||||
|
||||
|
||||
MySQL的查询操作
|
||||
单表查询:简单查询
|
||||
多表查询:连续查询
|
||||
联合查询
|
||||
|
||||
选择和投影
|
||||
投影:挑选要符合的字段
|
||||
选择:挑选符合条件的行
|
||||
|
||||
投影:select 字段1,字段2,... from tb_name
|
||||
selcet * from tb_name
|
||||
选择:select 字段1,字段2,.... from tb_name where 子句
|
||||
布尔条件表达式
|
||||
|
||||
布尔条件表达式操作符
|
||||
= 等值比较
|
||||
<=>:跟空值比较不会产生额外信息
|
||||
<>:不等值
|
||||
<:
|
||||
<=
|
||||
>
|
||||
>=
|
||||
|
||||
IS NULL:是否为空
|
||||
IS NOT NULL:是否不空
|
||||
LIKE:支持的通配符%(任意长度的任意字符) _(任意单个字符)
|
||||
RLIKE,REGEXP:支持使用正则表达式作为条件
|
||||
IN:判断某行的某一字段的值是否在给定的列表中
|
||||
BETWEEN...AND....:判断指定的值是否位于指定的范围之间
|
||||
|
||||
组合条件测试
|
||||
NOT |
|
||||
AND &&
|
||||
OR ||
|
||||
|
||||
排序
|
||||
order by ‘排序字段’
|
||||
默认为升序:ASC
|
||||
降序:DESC
|
||||
|
||||
内置的聚合函数
|
||||
sum():和
|
||||
AVG():平均值
|
||||
MAX():最大值
|
||||
MIN():最小值
|
||||
COUNT():个数统计
|
||||
|
||||
分组
|
||||
group by
|
||||
对分组的条件过滤
|
||||
having
|
||||
只返回有用的行
|
||||
LIMIT
|
||||
一个数为显示的行数
|
||||
两个数字为偏移第一个数字行,显示第二个数字
|
||||
|
||||
select语句的执行流程
|
||||
from clause --> where clause --> group by --> having clause -->order by --> select -->limit
|
||||
|
||||
select语句
|
||||
distinct 重复的只显示一次
|
||||
SQL_CACHE 缓存查询结果
|
||||
SQL_NO_CACHE 不缓存查询结果
|
||||
|
||||
|
||||
MySQL多表查询和子查询
|
||||
|
||||
联结查询:事先将两张或者多张表join,根据join的结果进行查询
|
||||
|
||||
cross join:交叉联结
|
||||
自然联结
|
||||
等值联结:把相同的字段进行等值连接
|
||||
|
||||
外联结:
|
||||
左外联接:只保留出现在左外连接元算之前(左边)的关系中的元组(以左表为准,)
|
||||
left_tb LEFT JOIN right_tb ON 条件
|
||||
右外联接:只保留出现在右外连接元算之后(右边)的关系中的元组(以右表为准)
|
||||
left_tb RIGHT JOIN right_tb ON 条件
|
||||
全外联接:
|
||||
|
||||
自联结:
|
||||
|
||||
别名:AS
|
||||
表别名:
|
||||
字段别名
|
||||
|
||||
子查询:在查询中嵌套的查询
|
||||
用于WHERE中的子查询
|
||||
1.用于比较表达式中的子查询
|
||||
子查询的返回值只能有一个
|
||||
2.用于EXISTS中的子查询
|
||||
判断存在与否
|
||||
3.用于IN中的子查询
|
||||
判断存在于指定列表中
|
||||
用于FROM中子查询
|
||||
select alias.col,....FROM(SELECT CLUSE) alias WHERE condition
|
||||
|
||||
MYSQL不擅长于子查询,应该避免使用子查询
|
||||
|
||||
总结:mysql的连接查询与子查询
|
||||
联结:
|
||||
交叉联结:
|
||||
内联结:
|
||||
外联结:
|
||||
左外
|
||||
右外
|
||||
自联结
|
||||
子查询:
|
||||
用于where中的子查询
|
||||
用于条件比较:
|
||||
用于exists
|
||||
用于IN中
|
||||
用于FROM
|
||||
|
||||
MYSQL的联合查询:
|
||||
把两个或多个查询语句的结果合并成一个结果进行输出
|
||||
select clauase union select clause union.....
|
||||
索引
|
||||
show indexs from tb_name 查看索引
|
||||
alter table tb_name add index(字段)
|
||||
创建索引
|
||||
|
||||
explain 解释命令,查看命令的执行过程
|
||||
|
||||
MYSQL视图(虚表)
|
||||
存储下来的select语句
|
||||
创建:
|
||||
create view 视图名 as select语句
|
||||
删除:
|
||||
drop view 视图名
|
84
数据库/mysql/mysql备份恢复
Normal file
84
数据库/mysql/mysql备份恢复
Normal file
|
@ -0,0 +1,84 @@
|
|||
备份对象:
|
||||
数据
|
||||
配置文件
|
||||
代码:存储过程,存储函数,触发器
|
||||
OS相关的配置文件,如crontab及相关脚本等
|
||||
|
||||
跟复制相关的配置:二进制日志文件
|
||||
|
||||
备份工具:
|
||||
mysqldump:逻辑备份工具
|
||||
InnoDB热备、MyISAM温备、Aria温备
|
||||
备份和恢复过程慢
|
||||
mysqldumper:多线程的mysqldump
|
||||
难实现差异或增量备份
|
||||
|
||||
lvm-snapshot:
|
||||
接近于热备的工具,因为要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁
|
||||
使用cp、tar等工具物理备份,备份与恢复速度快
|
||||
难以实现增量备份,并且请求全局锁需要等待一段时间,在繁忙的服务器上更慢
|
||||
|
||||
select clause into outfile '/path/to/somefile'(备份)
|
||||
load data infile '/path/from/somefile' (恢复)
|
||||
部分备份工具,不会备份关系定义,仅备份表中的数据
|
||||
逻辑备份工具,快于mysqldump
|
||||
|
||||
Innobase:商业备份工具,Innobackup
|
||||
Xtrabackup:开源备份工具
|
||||
InnoDB热备,增量备份
|
||||
MyISAM温备,不支持增量
|
||||
物理备份,速度快
|
||||
|
||||
|
||||
mysqldump:适用于数据量较小的情况(注意备份前要加锁)
|
||||
mysqldump [options] [db_name] [tb_name]
|
||||
备份单个数据库:mysqldump -u 用户名 -h 主机 -p 数据库 > 备份文件
|
||||
恢复时,如果目标库不存在,需要事先手动备份 mysql -u 用户名 -h 主机名 -p 数据库名 < 备份文件
|
||||
|
||||
备份所有库:mysqldump --all-database > 备份文件
|
||||
备份指定多个库: mysqldump --databases db1 db2
|
||||
|
||||
|
||||
--lock-all-tables:请求锁定所有表之后再备份,对InnoDB,MyISAM,Aria做温备
|
||||
--single-transaction:能够对InnoDB存储引擎实现热备
|
||||
|
||||
备份代码:
|
||||
--events:备份事件调度器代码
|
||||
--routines:备份存储过程与存储函数
|
||||
--triggers:备份触发器
|
||||
备份时滚动日志
|
||||
--flush-logs:备份前、请求到锁之后滚动日志
|
||||
复制时的同步位置标记
|
||||
--master-data=[0|1|2]
|
||||
0:不记录
|
||||
1:记录为change master语句
|
||||
2、记录为注释的change master语句
|
||||
|
||||
备份InnoDB存储引擎的数据库:mysqldump --database 数据库 --single-transaction -flush-logs --master-data=2 > 数据文件
|
||||
备份MyISAM存储引擎的数据库:mysqldump --database 数据库 --lock-all-tables -flush-logs --master-data=2 > 数据文件
|
||||
|
||||
|
||||
恢复时,查看备份文件中记录的标记位置(--master-data=2参数实现,mysqlbinlog文件中的位置)
|
||||
关闭其他连接,然后使用mysqlbinlog --start-position=标记位置 --end-position=结束标记 binlog文件 > 恢复文件
|
||||
关闭binlog日志记录([交互]set session sql_log_bin=0)
|
||||
执行全量备份脚本及binlog中抽出的数据文件
|
||||
开启binlog日志记录([交互]set session sql_log_bin=1)
|
||||
|
||||
滚动二进制文件:mysqldump flush-logs
|
||||
|
||||
lvm-snapshot:
|
||||
step1: 锁表,保证数据的一致性。flush table with read lock;
|
||||
|
||||
step2:滚动日志flush logs;
|
||||
|
||||
step3:查看master二进制当前的状态,以便slave的复制使用,或者其他的恢复使用。show master status;
|
||||
|
||||
step4: 为mysql数据目录所在的lvm做快照(-p r只读) lvcreate -s -n sqlbak_snap -L 100M -p r /dev/sqlbak/sqlbck_lv
|
||||
|
||||
step5: 解锁unlock tables;
|
||||
|
||||
step6: 挂载快照卷到一个目录下
|
||||
|
||||
就可以读取里面的数据。当然也可以mv到其他的目录下用来恢复。
|
||||
|
||||
step7: 卸载快照卷。删除快照卷 lvremove /dev/sqlbak/sqlbck_lv
|
165
数据库/mysql/mysql导入导出.html
Normal file
165
数据库/mysql/mysql导入导出.html
Normal file
|
@ -0,0 +1,165 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="tool" content="leanote-desktop-app">
|
||||
<title>mysql导入导出</title>
|
||||
<style>
|
||||
|
||||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*公用文字样式*/
|
||||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||||
.note-container{
|
||||
width:850px;
|
||||
margin:auto;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 1px 1px 10px #eee;
|
||||
}
|
||||
#title {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin-bottom: 16px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: none;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
table tr:nth-child(2n) {
|
||||
background-color: rgb(247, 247, 249);
|
||||
}
|
||||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||||
border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
blockquote {
|
||||
border-left-width:10px;
|
||||
background-color:rgba(128,128,128,0.05);
|
||||
border-top-right-radius:5px;
|
||||
border-bottom-right-radius:5px;
|
||||
padding:15px 20px;
|
||||
border-left:5px solid rgba(128,128,128,0.075);
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom:1.1em;
|
||||
font-size:1em;
|
||||
line-height:1.45
|
||||
}
|
||||
blockquote ul:last-child,blockquote ol:last-child {
|
||||
margin-bottom:0
|
||||
}
|
||||
pre {
|
||||
padding: 18px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
font-size: 90%;
|
||||
color: #c7254e;
|
||||
white-space: nowrap;
|
||||
background-color: #f9f2f4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footnote {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
pre {
|
||||
word-break:break-word
|
||||
}
|
||||
p,pre,pre.prettyprint,blockquote {
|
||||
margin:0 0 1.1em
|
||||
}
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
.sequence-diagram,.flow-chart {
|
||||
text-align:center;
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
.sequence-diagram text,.flow-chart text {
|
||||
font-size:15px !important;
|
||||
font-family:"Source Sans Pro",sans-serif !important
|
||||
}
|
||||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||||
fill:#f6f6f6
|
||||
}
|
||||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||||
stroke:#3f3f3f
|
||||
}
|
||||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||||
stroke:none
|
||||
}
|
||||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||||
fill:#3f3f3f
|
||||
}
|
||||
ul,ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
ul ul,ol ul,ul ol,ol ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
kbd {
|
||||
padding:.1em .6em;
|
||||
border:1px solid rgba(63,63,63,0.25);
|
||||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
font-size:.7em;
|
||||
font-family:sans-serif;
|
||||
background-color:#fff;
|
||||
color:#333;
|
||||
border-radius:3px;
|
||||
display:inline-block;
|
||||
margin:0 .1em;
|
||||
white-space:nowrap
|
||||
}
|
||||
.toc ul {
|
||||
list-style-type:none;
|
||||
margin-bottom:15px
|
||||
}
|
||||
</style>
|
||||
<!-- 该css供自定义样式 -->
|
||||
<link href="../leanote-html.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="note-container">
|
||||
<h1 class="title" id="leanote-title">mysql导入导出</h1>
|
||||
<div class="content-html" id="leanote-content"><div><a href="http://www.cnblogs.com/jiunadianshi/articles/2022334.html" data-mce-href="http://www.cnblogs.com/jiunadianshi/articles/2022334.html">linux下导入、导出mysql数据库命令</a></div><div>一、导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径):</div><div>1、导出数据和表结构:</div><div>mysqldump -u用户名 -p密码 数据库名 > 数据库名.sql</div><div>#/usr/local/mysql/bin/ mysqldump -uroot -p abc > abc.sql</div><div>敲回车后会提示输入密码</div><div>2、只导出表结构</div><div>mysqldump -u用户名 -p密码 -d 数据库名 > 数据库名.sql</div><div>#/usr/local/mysql/bin/ mysqldump -uroot -p -d abc > abc.sql</div><div>注:/usr/local/mysql/bin/ ---> mysql的data目录</div><div><br></div><div>二、导入数据库</div><div>1、首先建空数据库</div><div>mysql>create database abc;</div><div>2、导入数据库</div><div>方法一:</div><div>(1)选择数据库</div><div>mysql>use abc;</div><div>(2)设置数据库编码</div><div>mysql>set names utf8;</div><div>(3)导入数据(注意sql文件的路径)</div><div>mysql>source /home/abc/abc.sql;</div><div>方法二:</div><div>mysql -u用户名 -p密码 数据库名 < 数据库名.sql</div><div>#mysql -uabc_f -p abc < abc.sql</div><div>建议使用第二种方法导入。</div><div>注意:有命令行模式,有sql命令</div></div>
|
||||
</div>
|
||||
|
||||
<!-- 该js供其它处理 -->
|
||||
<script src="../leanote-html.js"></script>
|
||||
</body>
|
||||
</html>
|
8
数据库/mysql/主从复制原理与配置.md
Normal file
8
数据库/mysql/主从复制原理与配置.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
### 原理
|
||||
master节点将数据的改变记录到二进制binlog中,slave会在一定时间间隔内对master二进制进行探测,若发生改变,那就开始一个io_thread请求master的二进制binlog,master启动一个log dump线程,发送二进制文件给slave,并保存在slave节点的中继日志relay log中,slave使用sql_thread从中继日志读取二进制文件,在本地重放,使得slave的数据与主节点保持一致,最后io_thread和sql_thread休眠,等待下次被唤醒
|
||||
|
||||
### 配置
|
||||
1、主库my.cnf需要配置server_id,bin_log(server_id唯一)
|
||||
2、主节点创建一个具有复制权限的用户,show master status查看master状态,记录当前的log_bin文件和position
|
||||
3、从节点my.cnf需要配置server_id,read_only=true(防止在从节点执行update等操作,但是对高权限的用户无效)
|
||||
4、从节点执行change master to master_host=xxx,master_port=xxx,master_user=xxx,master_password=xxx,log_file='master-log-bin.xxxx',log_pos=xxx ,然后start slave,可以通过show slave status\G,查看状态
|
55
数据库/mysql/主从复制延迟原因及解决方法.md
Normal file
55
数据库/mysql/主从复制延迟原因及解决方法.md
Normal file
|
@ -0,0 +1,55 @@
|
|||
### 原因
|
||||
2)1)、MySQL数据库主从同步延迟原理mysql主从同步原理:主库针对写操作,顺序写binlog,从库单线程去主库顺序读”写操作的binlog”,从库取到binlog在本地原样执行(随机写),来保证主从数据逻辑上一致。mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlog,binlog是顺序写,所以效率很高,slave的Slave_IO_Running线程到主库取日志,效率比较高,下一步,问题来了,slave的Slave_SQL_Running线程将主库的DDL和DML操作在slave实施。DML和DDL的IO操作是随即的,不是顺序的,成本高很多,还可能slave上的其他查询产生lock争用,由于Slave_SQL_Running也是单线程的,所以一个DDL卡主了,需要执行10分钟,那么所有之后的DDL会等待这个DDL执行完才会继续执行,这就导致了延时。有朋友会问:“主库上那个相同的DDL也需要执行10分,为什么slave会延时?”,答案是master可以并发,Slave_SQL_Running线程却不可以。
|
||||
|
||||
2)、MySQL数据库主从同步延迟是怎么产生的?当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。首要原因:数据库在业务上读写压力太大,CPU计算负荷大,网卡负荷大,硬盘随机IO太高次要原因:读写binlog带来的性能影响,网络传输延迟。
|
||||
|
||||
### 方案
|
||||
1)、架构方面
|
||||
|
||||
1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。
|
||||
|
||||
2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。
|
||||
|
||||
3.服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。
|
||||
|
||||
4.不同业务的mysql物理上放在不同机器,分散压力。
|
||||
|
||||
5.使用比主库更好的硬件设备作为slave总结,mysql压力小,延迟自然会变小。
|
||||
|
||||
2)、硬件方面
|
||||
|
||||
1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。
|
||||
|
||||
2.存储用ssd或者盘阵或者san,提升随机写的性能。
|
||||
|
||||
3.主从间保证处在同一个交换机下面,并且是万兆环境。
|
||||
|
||||
总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。
|
||||
|
||||
3)、mysql主从同步加速
|
||||
|
||||
1、sync_binlog在slave端设置为0
|
||||
|
||||
2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
|
||||
|
||||
3、直接禁用slave端的binlog
|
||||
|
||||
4、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2
|
||||
|
||||
4)、从文件系统本身属性角度优化
|
||||
|
||||
master端修改linux、Unix文件系统中文件的etime属性, 由于每当读文件时OS都会将读取操作发生的时间回写到磁盘上,对于读操作频繁的数据库文件来说这是没必要的,只会增加磁盘系统的负担影响I/O性能。可以通过设置文件系统的mount属性,组织操作系统写atime信息,在linux上的操作为:打开/etc/fstab,加上noatime参数/dev/sdb1 /data reiserfs noatime 1 2然后重新mount文件系统#mount -oremount /data
|
||||
|
||||
5)、同步参数调整主库是写,对数据安全性较高,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设置是需要的而slave则不需要这么高的数据安全,完全可以讲sync_binlog设置为0或者关闭binlog,innodb_flushlog也可以设置为0来提高sql的执行效率
|
||||
|
||||
1、sync_binlog=1 oMySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去。默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。
|
||||
|
||||
如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。
|
||||
|
||||
对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。所以很多MySQL DBA设置的sync_binlog并不是最安全的1,而是2或者是0。这样牺牲一定的一致性,可以获得更高的并发和性能。默认情况下,并不是每次写入时都将binlog与硬盘同步。因此如果操作系统或机器(不仅仅是MySQL服务器)崩溃,有可能binlog中最后的语句丢失了。要想防止这种情况,你可以使用sync_binlog全局变量(1是最安全的值,但也是最慢的),使binlog在每N次binlog写入后与硬盘同步。即使sync_binlog设置为1,出现崩溃时,也有可能表内容和binlog内容之间存在不一致性。
|
||||
|
||||
2、innodb_flush_log_at_trx_commit (这个很管用)抱怨Innodb比MyISAM慢 100倍?那么你大概是忘了调整这个值。默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电池供电缓存(Battery backed up cache)时。设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。日志仍然会每秒flush到硬 盘,所以你一般不会丢失超过1-2秒的更新。设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。而值2只会在整个操作系统 挂了时才可能丢数据。
|
||||
|
||||
3、ls(1) 命令可用来列出文件的 atime、ctime 和 mtime。
|
||||
|
||||
atime 文件的access time 在读取文件或者执行文件时更改的ctime 文件的create time 在写入文件,更改所有者,权限或链接设置时随inode的内容更改而更改mtime 文件的modified time 在写入文件时随文件内容的更改而更改ls -lc filename 列出文件的 ctimels -lu filename 列出文件的 atimels -l filename 列出文件的 mtimestat filename 列出atime,mtime,ctimeatime不一定在访问文件之后被修改因为:使用ext3文件系统的时候,如果在mount的时候使用了noatime参数那么就不会更新atime信息。这三个time stamp都放在 inode 中.如果mtime,atime 修改,inode 就一定会改, 既然 inode 改了,那ctime也就跟着改了.之所以在 mount option 中使用 noatime, 就是不想file system 做太多的修改, 而改善读取效能
|
13
数据库/mysql/主备复制.md
Normal file
13
数据库/mysql/主备复制.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
备库B和主库A之间维持了一个长连接。主库A内部有一个线程,专门用于服务备库B的这个长连接。一个事务日志同步的完整过程如下:
|
||||
|
||||
1.在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量
|
||||
|
||||
2.在备库B上执行start slave命令,这时备库会启动两个线程,io_thread和sql_thread。其中io_thread负责与主库建立连接
|
||||
|
||||
3.主库A校验完用户名、密码后,开始按照备库B传过来的位置,从本地读取binlog,发给B
|
||||
|
||||
4.备库B拿到binlog后,写到本地文件,称为中转日志
|
||||
|
||||
5.sql_thread读取中转日志,解析出日志里的命令,并执行
|
||||
|
||||
由于多线程复制方案的引入,sql_thread演化成了多个线程
|
45
数据库/mysql/命令行ssh通道连接mysql.md
Normal file
45
数据库/mysql/命令行ssh通道连接mysql.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
#### 背景说明如下
|
||||
为了安全,mysql数据库安装在内网环境,外网无法直连,只能通过与数据库在同一个内网的、可以与外网通信的服务器连接,即使用ssh隧道连接。
|
||||
一般的第三方可视化客户端连接工具都可以配置ssh隧道。若使用命令行连接,就需要使用命令建立隧道。
|
||||
|
||||
##### 建立隧道命令如下:
|
||||
|
||||
```
|
||||
# 需要连接数据库的外网环境,执行下列命令
|
||||
ssh -p {ssh_port} -i {rsa_file} -fNL {local_port}:{mysql_ip}:{mysql_port} {ssh_user}@{ssh_ip}
|
||||
```
|
||||
###### 命令详解:
|
||||
* -p {ssh_port}: 指定跳板机器的ssh服务的端口(也就是B服务器)
|
||||
* -i {rsa_file}:指定连接跳板机的ssh公钥,由跳板机的ssh服务端生成,如果不指定公钥或者公钥验证失败则会弹出密码进行登录。(如果需要密码登录可以不填-i)
|
||||
* -f:告诉SSH客户端在后台运行(也就是执行命令之后在进程监听,需要关闭直接kill)
|
||||
* -N:只进行端口转发,不执行命令
|
||||
* -L:指定连接服务的格式 [bind_address:]port:host:hostport
|
||||
* {local_port}:本地监听的端口
|
||||
* {mysql_ip}:转发到的mysql的ip或域名(远程mysql主机地址)
|
||||
* {mysql_port}:转发到的mysql的端口
|
||||
* {ssh_port}:跳板机的
|
||||
* {ssh_user}:跳板机的ssh用户名(如果为rsa登录,则ras对应的用户名和ssh_user一致)
|
||||
* {ssh_ip}:跳板机的ip或域名
|
||||
|
||||
##### 连接数据库命令:
|
||||
|
||||
```
|
||||
mysql -h127.0.0.1 -P {local_port} -u{mysql_user} -p
|
||||
```
|
||||
#### 举例说明
|
||||
A:需要连接数据库的外网服务器(centos 8)
|
||||
B:只有内网地址或只能被特定主机连接的数据库服务器。数据库连接为:172.16.0.35:3306
|
||||
C:可以被A直连,与B在同一个内网中/或可以连接B。公网地址为:3.3.3.3,连接公钥为:rsa_pub.pem
|
||||
###### 1、建立隧道
|
||||
*A执行*
|
||||
```
|
||||
ssh -p 22 -i rsa_pub.pem -fNL 3320:172.16.0.35:3306 root@3.3.3.3
|
||||
```
|
||||
###### 2、查看本地监听端口
|
||||
```
|
||||
ss -anltp | grep 3320
|
||||
```
|
||||
###### 3、连接数据库
|
||||
```
|
||||
mysql -h 127.0.0.1 -P 3320 -u admin -p
|
||||
```
|
8
数据库/mysql/异步复制、同步复制、半同步复制.md
Normal file
8
数据库/mysql/异步复制、同步复制、半同步复制.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
#### 异步复制(Asynchronous replication)
|
||||
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
|
||||
|
||||
#### 全同步复制(Fully synchronous replication)
|
||||
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
|
||||
|
||||
#### 半同步复制(Semisynchronous replication)
|
||||
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
|
31
数据库/mysql/简单mysql主从复制
Normal file
31
数据库/mysql/简单mysql主从复制
Normal file
|
@ -0,0 +1,31 @@
|
|||
要求:
|
||||
1、主从mysql版本要一致
|
||||
2、若版本不一致,主版本要低于从
|
||||
3、从头开始或主服务器数据备份,从服务器恢复数据,并从主备份所在位置进行服务
|
||||
|
||||
注意(都需要启动):
|
||||
1、时间需要同步
|
||||
2、配置文件
|
||||
主:my.cnf
|
||||
修改二进制日志存放位置(安全)log-bin=目录/文件
|
||||
修改二进制文件的格式为binlog_format=mixed
|
||||
修改服务id server-id=1
|
||||
从:my.cnf
|
||||
要从主服务器复制二进制日志,所以从的二进制文件要关闭log-bin=OFF或注释掉
|
||||
修改服务id与主服务器不同,如 server-id=11
|
||||
添加复制日志relay-log=目录/文件
|
||||
只读read-only=on(仅限制不具备super权限用户无法执行的写操作)
|
||||
3、主从复制的事务安全
|
||||
在主服务器上配置sync_binlog=1(事务提交即同步)
|
||||
|
||||
|
||||
1、主服务器(执行)创建一个有复制权限的用户,并授权
|
||||
grant replication slave, replication client on *.* to 'rep'@'从ip地址' identified by 'reppass';
|
||||
flush plivileges;
|
||||
2、备份主服务器上数据,需要包含position信息(在导出的数据文件头部)
|
||||
备份InnoDB存储引擎的数据库:mysqldump --all-database --single-transaction -flush-logs --master-data=2 > 数据文件
|
||||
备份MyISAM存储引擎的数据库:mysqldump --all-database --lock-all-tables -flush-logs --master-data=2 > 数据文件
|
||||
3、从服务器(执行)连接主服务器
|
||||
change master to MASTER_HOST='主服务器ip' MASTER_USER='主服务器用户' MASTER_PASSWORD='密码' MASTER_PORT='端口' MASTER_LOG_FILE='主服务器二进制文件' MASTER_LOG_POS=从主服务器二进制文件位置读取
|
||||
4、从服务器启动slave(执行)
|
||||
start slave
|
3
数据库/mysql/索引.md
Normal file
3
数据库/mysql/索引.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
索引是帮助数据库高效获取数据的*排好序*的*数据结构*
|
||||
聚簇索引(聚集索引),索引与数据放在一起,索引结构的叶子节点保存了行数据
|
||||
非聚簇索引,索引与数据不放在一起,索引结构的叶子节点指向了数据对应的位置
|
7
数据库/mysql/锁.md
Normal file
7
数据库/mysql/锁.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
*读锁* :也叫共享锁、S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
|
||||
|
||||
*写锁* :又称排他锁、X锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
|
||||
|
||||
*表锁* :操作对象是数据表。Mysql大多数锁策略都支持,是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行。
|
||||
|
||||
*行级锁* :操作对象是数据表中的一行。是MVCC技术用的比较多的。行级锁对系统开销较大,但处理高并发较好。
|
28
数据库/oracle/oracle创建数据库
Normal file
28
数据库/oracle/oracle创建数据库
Normal file
|
@ -0,0 +1,28 @@
|
|||
<<<<<<< HEAD
|
||||
|
||||
创建数据库文件
|
||||
CREATE TABLESPACE insurance LOGGING DATAFILE '/data/database/orcl/insurance.dbf' SIZE 100M AUTOEXTEND ON NEXT 32M MAXSIZE 500M EXTENT MANAGEMENT LOCAL;
|
||||
|
||||
创建数据库临时文件
|
||||
create temporary TABLESPACE insurance_temp tempfile '/data/database/orcl/insurance_temp.dbf' SIZE 100M AUTOEXTEND ON NEXT 32M MAXSIZE 500M EXTENT MANAGEMENT LOCAL;
|
||||
|
||||
创建用户与上述两个文件形成映射关系
|
||||
CREATE USER insurance IDENTIFIED BY "Insur@nce#20" DEFAULT TABLESPACE insurance TEMPORARY TABLESPACE insurance_temp;
|
||||
|
||||
添加用户权限
|
||||
grant connect,resource,dba to insurance;
|
||||
=======
|
||||
|
||||
创建数据库文件
|
||||
CREATE TABLESPACE insurance LOGGING DATAFILE '/data/database/orcl/insurance.dbf' SIZE 100M AUTOEXTEND ON NEXT 32M MAXSIZE 500M EXTENT MANAGEMENT LOCAL;
|
||||
|
||||
创建数据库临时文件
|
||||
create temporary TABLESPACE insurance_temp tempfile '/data/database/orcl/insurance_temp.dbf' SIZE 100M AUTOEXTEND ON NEXT 32M MAXSIZE 500M EXTENT MANAGEMENT LOCAL;
|
||||
|
||||
创建用户与上述两个文件形成映射关系
|
||||
CREATE USER insurance IDENTIFIED BY "Insur@nce#20" DEFAULT TABLESPACE insurance TEMPORARY TABLESPACE insurance_temp;
|
||||
|
||||
添加用户权限
|
||||
grant connect,resource,dba to insurance;
|
||||
>>>>>>> 28bec05... 20200611
|
||||
grant create session to insurance;
|
57
数据库/oracle/oracle启动与登陆.txt
Normal file
57
数据库/oracle/oracle启动与登陆.txt
Normal file
|
@ -0,0 +1,57 @@
|
|||
1.进入到sqlplus启动实例
|
||||
[oracle@redhat ~]$ su - oracle --“切换到oracle用户”
|
||||
Password:
|
||||
[oracle@redhat ~]$ lsnrctl start --“打开监听”
|
||||
LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 14-OCT-2009 19:06:40
|
||||
Copyright (c) 1991, 2005, Oracle. All rights reserved.
|
||||
Starting /home/oracle/product/10g/bin/tnslsnr: please wait...
|
||||
TNSLSNR for Linux: Version 10.2.0.1.0 - Production
|
||||
System parameter file is /home/oracle/product/10g/network/admin/listener.ora
|
||||
Log messages written to /home/oracle/product/10g/network/log/listener.log
|
||||
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC2)))
|
||||
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=redhat)(PORT=1522)))
|
||||
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC2)))
|
||||
STATUS of the LISTENER
|
||||
------------------------
|
||||
Alias LISTENER
|
||||
Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production
|
||||
Start Date 14-OCT-2009 19:06:40
|
||||
Uptime 0 days 0 hr. 0 min. 0 sec
|
||||
Trace Level off
|
||||
Security ON: Local OS Authentication
|
||||
SNMP OFF
|
||||
Listener Parameter File /home/oracle/product/10g/network/admin/listener.ora
|
||||
Listener Log File /home/oracle/product/10g/network/log/listener.log
|
||||
Listening Endpoints Summary...
|
||||
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC2)))
|
||||
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=redhat)(PORT=1522)))
|
||||
Services Summary...
|
||||
Service "PLSExtProc" has 1 instance(s).
|
||||
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
|
||||
The command completed successfully
|
||||
[oracle@redhat ~]$ sqlplus /nolog --“进入到sqlplus”
|
||||
SQL*Plus: Release 10.2.0.1.0 - Production on Wed Oct 14 19:06:45 2009
|
||||
Copyright (c) 1982, 2005, Oracle. All rights reserved.
|
||||
SQL> conn /as sysdba --“连接到sysdba”
|
||||
Connected to an idle instance.
|
||||
SQL> startup --“启动数据库实例”
|
||||
ORACLE instance started.
|
||||
Total System Global Area 285212672 bytes
|
||||
Fixed Size 1218968 bytes
|
||||
Variable Size 88082024 bytes
|
||||
Database Buffers 188743680 bytes
|
||||
Redo Buffers 7168000 bytes
|
||||
Database mounted.
|
||||
Database opened.
|
||||
SQL> shutdown immediate --“关闭数据库实例”
|
||||
Database closed.
|
||||
Database dismounted.
|
||||
ORACLE instance shut down.
|
||||
SQL> exit
|
||||
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
|
||||
With the Partitioning, OLAP and Data Mining options
|
||||
[oracle@redhat ~]$ lsnrctl stop --“关闭监听”
|
||||
LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 14-OCT-2009 19:08:06
|
||||
Copyright (c) 1991, 2005, Oracle. All rights reserved.
|
||||
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC2)))
|
||||
The command completed successfully
|
12
数据库/oracle/oracle基本操作.md
Normal file
12
数据库/oracle/oracle基本操作.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
### 添加select权限
|
||||
```
|
||||
grant select on USER1.TABLE to USER2;
|
||||
```
|
||||
### 添加创建同义词权限
|
||||
```
|
||||
grant create synonym to USER2;
|
||||
```
|
||||
### 创建同义词
|
||||
```
|
||||
create or replace synonym TABLE for USER1.TABLE;
|
||||
```
|
1
数据库/oracle/oracle导出数据.txt
Normal file
1
数据库/oracle/oracle导出数据.txt
Normal file
|
@ -0,0 +1 @@
|
|||
exp user/pwd@dbname file=d:text.dmp owner=(user)
|
BIN
数据库/oracle/oracle数据库数据导入导出步骤(入门) - CSDN博客.pdf
Normal file
BIN
数据库/oracle/oracle数据库数据导入导出步骤(入门) - CSDN博客.pdf
Normal file
Binary file not shown.
86
数据库/oracle/oracle表空间扩容.md
Normal file
86
数据库/oracle/oracle表空间扩容.md
Normal file
|
@ -0,0 +1,86 @@
|
|||
```sql
|
||||
# 查询表空间
|
||||
SELECT TABLESPACE_NAME "表空间",
|
||||
To_char(Round(BYTES / 1024, 2), '99990.00')
|
||||
|| '' "实有",
|
||||
To_char(Round(FREE / 1024, 2), '99990.00')
|
||||
|| 'G' "现有",
|
||||
To_char(Round(( BYTES - FREE ) / 1024, 2), '99990.00')
|
||||
|| 'G' "使用",
|
||||
To_char(Round(10000 * USED / BYTES) / 100, '99990.00')
|
||||
|| '%' "比例"
|
||||
FROM (SELECT A.TABLESPACE_NAME TABLESPACE_NAME,
|
||||
Floor(A.BYTES / ( 1024 * 1024 )) BYTES,
|
||||
Floor(B.FREE / ( 1024 * 1024 )) FREE,
|
||||
Floor(( A.BYTES - B.FREE ) / ( 1024 * 1024 )) USED
|
||||
FROM (SELECT TABLESPACE_NAME TABLESPACE_NAME,
|
||||
Sum(BYTES) BYTES
|
||||
FROM DBA_DATA_FILES
|
||||
GROUP BY TABLESPACE_NAME) A,
|
||||
(SELECT TABLESPACE_NAME TABLESPACE_NAME,
|
||||
Sum(BYTES) FREE
|
||||
FROM DBA_FREE_SPACE
|
||||
GROUP BY TABLESPACE_NAME) B
|
||||
WHERE A.TABLESPACE_NAME = B.TABLESPACE_NAME)
|
||||
--WHERE TABLESPACE_NAME LIKE 'CDR%' --这一句用于指定表空间名称
|
||||
ORDER BY Floor(10000 * USED / BYTES) DESC;
|
||||
```
|
||||
```
|
||||
set linesize 140 pagesize 10000
|
||||
col "Status" for a10
|
||||
col "Name" for a25
|
||||
col "Type" for a10
|
||||
col "Extent" for a15
|
||||
col "Size(M)" for a15
|
||||
col "Used(M)" for a15
|
||||
col "Used(%)" for a20
|
||||
col "Maxused(%)" for a20
|
||||
SELECT d.status "Status", d.tablespace_name "Name", d.contents "Type", d.extent_management "Extent",
|
||||
TO_CHAR(NVL(a.bytes / 1024 / 1024, 0),'99,999,990') "Size(M)",
|
||||
TO_CHAR(NVL(a.bytes - NVL(f.bytes, 0), 0)/1024/1024,'999,999,999') "Used(M)",
|
||||
TO_CHAR(NVL((a.bytes - NVL(f.bytes, 0)) / a.bytes * 100, 0), '900.00') "Used(%)",
|
||||
TO_CHAR(100-((a.maxbytes - a.bytes + f.bytes) / a.maxbytes * 100), '900.00') "Maxused(%)"
|
||||
FROM sys.dba_tablespaces d,
|
||||
(select tablespace_name, sum(bytes) bytes,sum(decode(autoextensible, 'YES',maxbytes,'NO', bytes)) maxbytes from dba_data_files group by tablespace_name) a,
|
||||
(select tablespace_name, sum(bytes) bytes from dba_free_space group by tablespace_name) f
|
||||
WHERE d.tablespace_name = a.tablespace_name(+) AND d.tablespace_name = f.tablespace_name(+) AND NOT
|
||||
(d.extent_management like 'LOCAL' AND d.contents like 'TEMPORARY')
|
||||
UNION ALL
|
||||
SELECT d.status "Status", d.tablespace_name "Name", d.contents "Type", d.extent_management "Extent",
|
||||
TO_CHAR(NVL(a.bytes / 1024 / 1024, 0),'99,999,999') "Size(M)",
|
||||
TO_CHAR(NVL(t.bytes,0)/1024/1024,'999,999,999') "Used(M)",
|
||||
TO_CHAR(NVL(t.bytes / a.bytes * 100, 0), '990.00') "Used(%)" ,
|
||||
TO_CHAR(NVL(t.bytes / a.maxbytes * 100, 0), '990.00') "Maxused(%)"
|
||||
FROM sys.dba_tablespaces d,
|
||||
(select tablespace_name, sum(bytes) bytes,sum(decode(autoextensible, 'YES',maxbytes,'NO', bytes)) maxbytes from dba_temp_files group by tablespace_name) a,
|
||||
(select tablespace_name, sum(bytes_cached) bytes from v$temp_extent_pool group by tablespace_name) t
|
||||
WHERE d.tablespace_name = a.tablespace_name(+) AND d.tablespace_name = t.tablespace_name(+) AND
|
||||
d.extent_management like 'LOCAL' AND d.contents like 'TEMPORARY'
|
||||
ORDER BY 7;
|
||||
```
|
||||
```sql
|
||||
# 查询表空间文件及目录
|
||||
select
|
||||
b.file_name 物理文件名,
|
||||
b.tablespace_name 表空间,
|
||||
b.bytes/1024/1024 大小M,
|
||||
(b.bytes-sum(nvl(a.bytes,0)))/1024/1024 已使用M,
|
||||
substr((b.bytes-sum(nvl(a.bytes,0)))/(b.bytes)*100,1,5) 利用率
|
||||
from dba_free_space a,dba_data_files b
|
||||
where a.file_id=b.file_id
|
||||
group by b.tablespace_name,b.file_name,b.bytes
|
||||
order by b.tablespace_name;
|
||||
```
|
||||
```
|
||||
select tablespace_name,file_id,bytes/1024/1024,file_name from dba_data_files order by file_id;
|
||||
```
|
||||
|
||||
```sql
|
||||
# 增加表空间文件
|
||||
ALTER TABLESPACE [表空间名称] ADD DATAFILE '数据文件路径' SIZE 8G;
|
||||
```
|
||||
|
||||
```sql
|
||||
# 查询归档日志空间使用情况
|
||||
select to_char(next_time, 'yyyy-mm-dd') hourtime, round(sum(blocks * block_size) / 1024 / 1024 / 1024) archlog_GB from v$archived_log where dest_id = 1 and next_time > sysdate - 15 group by to_char(next_time, 'yyyy-mm-dd') order by to_char(next_time, 'yyyy-mm-dd');
|
||||
```
|
12
数据库/oracle/oracle锁表问题.md
Normal file
12
数据库/oracle/oracle锁表问题.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
## 查询被锁定的表
|
||||
```
|
||||
select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;
|
||||
```
|
||||
## 查询发生锁定表的会话及序列号
|
||||
```
|
||||
select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time;
|
||||
```
|
||||
## 结束产生锁表的会话
|
||||
```
|
||||
alter system kill session 'SID,SERIAL#';
|
||||
```
|
21
数据库/oracle/查询资源所属用户.md
Normal file
21
数据库/oracle/查询资源所属用户.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
## 查询表所属用户
|
||||
```
|
||||
SELECT * FROM DBA_TABLES WHERE TABLE_NAME='表名';
|
||||
```
|
||||
```
|
||||
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE='TABLE' and OBJECT_NAME='表名'
|
||||
```
|
||||
```
|
||||
select owner from dba_tables where table_name=upper('表名');
|
||||
```
|
||||
## 查询视图所属用户
|
||||
```
|
||||
SELECT * FROM ALL_VIEWS WHERE VIEW_NAME='视图名';
|
||||
```
|
||||
```
|
||||
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE='VIEW' and OBJECT_NAME='视图名'
|
||||
```
|
||||
## 查询存储过程所属用户
|
||||
```
|
||||
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE='PROCEDURE' and OBJECT_NAME='存储过程名'
|
||||
```
|
BIN
数据库/postgresql/PostgreSQL CPU占用100%性能分析及慢sql优化.docx
Normal file
BIN
数据库/postgresql/PostgreSQL CPU占用100%性能分析及慢sql优化.docx
Normal file
Binary file not shown.
Binary file not shown.
25
数据库/postgresql/monitor.sh
Normal file
25
数据库/postgresql/monitor.sh
Normal file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Edit 2020/04/16
|
||||
|
||||
# sql script
|
||||
# https://blog.csdn.net/Hehuyi_In/article/details/95893869
|
||||
# example:
|
||||
# sql="select count(*) from pg_stat_activity where state='idle in transaction';"
|
||||
# message="处于空闲状态的会话"
|
||||
sql=""
|
||||
message=""
|
||||
|
||||
user=postgres
|
||||
source /home/$user/.bash_profile
|
||||
|
||||
|
||||
if [ $UID -ne `id -u $user` ];then
|
||||
echo -e "\033[31;1mNot Manager of PostgreSQL! \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get value
|
||||
valuse=`psql postgres -c "$sql" | sed -n '3p' | sed 's/ //g'`
|
||||
|
||||
echo "$message=$valuse"
|
27
数据库/postgresql/postgres-backup.sh
Normal file
27
数据库/postgresql/postgres-backup.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Edit 2020/4/10
|
||||
|
||||
backup=$PGDATA/../backup
|
||||
now=`date +%Y%m%d-%H%M%S`
|
||||
aweekago=`date -d -7days +%Y%m%d`
|
||||
|
||||
host=10.1.139.126
|
||||
port=5432
|
||||
username=yanzhao
|
||||
database=yzdb
|
||||
|
||||
if [ $UID -eq 0 ];then
|
||||
echo -e "\033[31m;1mDo not Use Root! \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source ~/.bash_profile
|
||||
|
||||
if [ ! -f $backup ];then
|
||||
mkdir -p $backup
|
||||
fi
|
||||
|
||||
pg_dump -h $host -p $port -U $username --no-password -d $database -F c -b -v -f $backup/$database-$now.bak
|
||||
|
||||
cd $backup && tar zcvf $database-$aweekago.tar.gz $database-$aweekago-* --remove-files
|
34
数据库/postgresql/postgresql-base-update.sh
Normal file
34
数据库/postgresql/postgresql-base-update.sh
Normal file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Edit 2020/04/15
|
||||
|
||||
user=postgres
|
||||
source /home/$user/.bash_profile
|
||||
|
||||
backup=$PGDATA/../backup
|
||||
today=`date +%F`
|
||||
aweekago=`date -d -7days +%F`
|
||||
|
||||
host=10.1.139.126
|
||||
port=5432
|
||||
username=rep
|
||||
|
||||
if [ $UID -ne `id -u $user` ];then
|
||||
echo -e "\033[31;1mNot Manager of PostgreSQL! \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create base backup
|
||||
echo -e "\033[33;1m---$today---\nBack up Now!\n---\033[0m"
|
||||
if [ -f "$backup/$today/base" ];then
|
||||
mkdir -p $backup/$today/base
|
||||
fi
|
||||
pg_basebackup -D $backup/$today/base -h $host -p $port -Ft -z -P -v -w -U $username
|
||||
echo -e "\033[33;1m---\n---Finish---\033[0m"
|
||||
|
||||
# switch wal
|
||||
psql postgres -c "checkpoint;"
|
||||
psql postgres -c "select pg_switch_wal();"
|
||||
|
||||
# clean backup 7 days ago
|
||||
rm -rf $backup/$aweekago
|
BIN
数据库/postgresql/postgresql备份恢复数据.docx
Normal file
BIN
数据库/postgresql/postgresql备份恢复数据.docx
Normal file
Binary file not shown.
BIN
数据库/postgresql/postgresql定位分析消耗CPU高的SQL语句.docx
Normal file
BIN
数据库/postgresql/postgresql定位分析消耗CPU高的SQL语句.docx
Normal file
Binary file not shown.
0
数据库/postgresql/postgresql恢复误删数据.docx
Normal file
0
数据库/postgresql/postgresql恢复误删数据.docx
Normal file
BIN
数据库/postgresql/postgresql数据库相关操作.docx
Normal file
BIN
数据库/postgresql/postgresql数据库相关操作.docx
Normal file
Binary file not shown.
Binary file not shown.
BIN
数据库/postgresql/postgresql的pg_stat_statements扩展.docx
Normal file
BIN
数据库/postgresql/postgresql的pg_stat_statements扩展.docx
Normal file
Binary file not shown.
Binary file not shown.
1
数据库/postgresql/修改用户密码.txt
Normal file
1
数据库/postgresql/修改用户密码.txt
Normal file
|
@ -0,0 +1 @@
|
|||
alter user rep with password 'yanzhao';
|
1
数据库/postgresql/创建数据库.txt
Normal file
1
数据库/postgresql/创建数据库.txt
Normal file
|
@ -0,0 +1 @@
|
|||
CREATE DATABASE exampledb OWNER dbuser;
|
11
数据库/postgresql/创建用户.txt
Normal file
11
数据库/postgresql/创建用户.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
创建quartztstopr用户并赋权限
|
||||
|
||||
1、创建用户(create role 与create user 区别只有create user默认加上login,而create role不加)
|
||||
postgres=# create user quartztstopr with password 'Quartztstopr@2018';
|
||||
2、切换到quartztst数据库
|
||||
postgres=# \c quartztst
|
||||
3、为用户赋增删改查权限
|
||||
quartztst=# grant select,update,delete,insert on all tables in schema public to quartztstopr; # 查询,删除,更新,插入
|
||||
quartztst=# grant all privileges on all tables in schema public to quartztstopr; # 所有权限
|
||||
4、为用户赋修改表字段权限
|
||||
quartztst=# grant all privileges on all tables in schema public to quartztstopr;
|
45
数据库/postgresql/导入导出数据.txt
Normal file
45
数据库/postgresql/导入导出数据.txt
Normal file
|
@ -0,0 +1,45 @@
|
|||
1、导入整个数据库
|
||||
|
||||
# psql -U postgres(用户名) 数据库名(缺省时同用户名) < /data/dum.sql
|
||||
|
||||
|
||||
2、导出整个数据库
|
||||
|
||||
# pg_dump -h localhost -U postgres(用户名) 数据库名(缺省时同用户名) >/data/dum.sql
|
||||
|
||||
|
||||
3、导出某个表
|
||||
|
||||
# pg_dump -h localhost -U postgres(用户名) 数据库名(缺省时同用户名) -t table(表名) >/data/dum.sql
|
||||
|
||||
|
||||
4、压缩方法
|
||||
|
||||
一般用dump导出数据会比较大,推荐使用xz压缩
|
||||
|
||||
压缩方法 xz dum.sql 会生成 dum.sql.xz 的文件
|
||||
|
||||
|
||||
5、xz压缩数据倒数数据库方法
|
||||
|
||||
xzcat /data/dum.sql.xz | psql -h localhost -U postgres(用户名) 数据库名(缺省时同用户名)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pg_dump -F c -f /dbbak/pgdumpbak/c.dmp -C -E UTF8 -h 127.0.0.1 -U postgres testdb #二进制格式备份文件
|
||||
|
||||
|
||||
|
||||
pg_dump -F p -f /dbbak/pgdumpbak/p.dmp -C -E UTF8 -h 127.0.0.1 -U postgres testdb #文本格式备份文件,”-C” 表示包含创建语句
|
||||
|
||||
n
|
||||
|
||||
pg_restore /dbbak/c.dmp|less 可以解析二进制格式的备份文件
|
||||
|
||||
pg_restore -l /dbbak/c.dmp
|
||||
|
||||
pg_restore -d testdb /dbbak/pgdumpbak/c.dmp #需要先创建目标库
|
||||
|
||||
pg_restore -d postgres /dbbak/pgdumpbak/p.dmp #文件中包含创建数据库的命令,不需要创建目标库
|
7
数据库/postgresql/批量修改表或视图的owner.txt
Normal file
7
数据库/postgresql/批量修改表或视图的owner.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
DO $$DECLARE r record;
|
||||
BEGIN
|
||||
FOR r IN SELECT tablename/viewname FROM pg_tables/pg_views WHERE schemaname = 'public'
|
||||
LOOP
|
||||
EXECUTE 'alter table '|| r.tablename/r.viewname ||' owner to new_owner;';
|
||||
END LOOP;
|
||||
END$$;
|
9
数据库/postgresql/查询所有库名.txt
Normal file
9
数据库/postgresql/查询所有库名.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
查询所有库名
|
||||
\l
|
||||
或
|
||||
SELECT datname FROM pg_database;
|
||||
|
||||
查询当前库下有哪些表
|
||||
\dt
|
||||
或者
|
||||
SELECT tablename FROM pg_tables;
|
6
数据库/postgresql/查询用户的权限.txt
Normal file
6
数据库/postgresql/查询用户的权限.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
查询cardbtstopr的权限
|
||||
|
||||
1、切换到cardbtst数据库
|
||||
postgres=# \c cardbtst
|
||||
2、查询权限
|
||||
cardbtst=# select * from information_schema.role_table_grants where grantee='cardbtstopr';
|
356
数据库/postgresql/理解PostgreSQL中的权限.txt
Normal file
356
数据库/postgresql/理解PostgreSQL中的权限.txt
Normal file
|
@ -0,0 +1,356 @@
|
|||
在postgresql中,database,schema,table之间关系
|
||||
从逻辑上看,schema、table都是位于database之下。在postgres数据库下建立表(相当于建立在public schema下),理解pg下的权限:
|
||||
\dp - lists table/view permissions
|
||||
\dn+ - lists schema permissions
|
||||
\l+ does not list all users that can access the database
|
||||
|
||||
using psql from postgres 8.4 and postgres 9.0, and the command \l or \l+ gives me column Access Privileges where I have entry:
|
||||
<user_name>=c/<database_name>
|
||||
|
||||
\dp显示的项解释如下:
|
||||
|
||||
角色名=xxxx -- 被授予给一个角色的特权
|
||||
=xxxx -- 被授予给 PUBLIC 的特权
|
||||
|
||||
r -- SELECT ("读")
|
||||
w -- UPDATE ("写")
|
||||
a -- INSERT ("追加")
|
||||
d -- DELETE
|
||||
D -- TRUNCATE
|
||||
x -- REFERENCES
|
||||
t -- TRIGGER
|
||||
X -- EXECUTE
|
||||
U -- USAGE
|
||||
C -- CREATE
|
||||
c -- CONNECT
|
||||
T -- TEMPORARY
|
||||
arwdDxt -- ALL PRIVILEGES (对于表,对其他对象会变化)
|
||||
* -- 用于前述特权的授权选项
|
||||
|
||||
/yyyy -- 授予该特权的角色
|
||||
|
||||
在PostgreSQL中,可以把角色划分为如下几类:
|
||||
|
||||
SELECT:该权限用来查询表或是表上的某些列,或是视图,序列。
|
||||
INSERT:该权限允许对表或是视图进行插入数据操作,也可以使用COPY FROM进行数据的插入。
|
||||
UPDATE:该权限允许对表或是或是表上特定的列或是视图进行更新操作。
|
||||
DELETE:该权限允许对表或是视图进行删除数据的操作。
|
||||
TRUNCATE:允许对表进行清空操作。
|
||||
REFERENCES:允许给参照列和被参照列上创建外键约束。
|
||||
TRIGGER:允许在表上创建触发器。
|
||||
CREATE:对于数据库,允许在数据库上创建Schema;对于Schema,允许对Schema上创建数据库对象;对于表空间,允许把表或是索引指定到对应的表空间上。
|
||||
CONNECT:允许用户连接到指定的数据库上。
|
||||
TEMPORARY或是TEMP:允许在指定数据库的时候创建临时表。
|
||||
EXECUTE:允许执行某个函数。
|
||||
USAGE:对于程序语言来说,允许使用指定的程序语言创建函数;对于Schema来说,允许查找该Schema下的对象;对于序列来说,允许使用currval和nextval函数;对于外部封装器来说,允许使用外部封装器来创建外部服务器;对于外部服务器来说,允许创建外部表。
|
||||
ALL PRIVILEGES:表示一次性给予可以授予的权限。
|
||||
|
||||
创建两个测试账号
|
||||
create role web login connection limit 9 password 'web_app';
|
||||
create role mobile login connection limit 9 password 'mob_ile';
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA dba GRANT SELECT ON TABLES TO mobile;
|
||||
没有起到作用,用下面的语句:
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA dba TO mobile;
|
||||
|
||||
从dba终端看是有权限的,但mobile中用\dpp却看不到,难道要重新登录一下?
|
||||
|
||||
重新登录后也看不到,试试下面的规则:
|
||||
GRANT CONNECT ON DATABASE dba TO mobile;
|
||||
GRANT USAGE ON SCHEMA dba TO mobile;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA dba TO mobile;
|
||||
GRANT SELECT ON ALL SEQUENCES IN SCHEMA dba to mobile;
|
||||
单表授权
|
||||
GRANT SELECT,INSERT,UPDATE ON TABLE web9 TO web;
|
||||
|
||||
成功。
|
||||
|
||||
后来发现是search_path这个变量的问题,在当前的变量中没有包含dba,所以\dpp时看不见,但从其中的表中取数据是可以的:select * from dba.table limit 9;
|
||||
|
||||
If your read-only user doesn't have permission to list tables (i.e. \d returns no results), it's probably because you don't have USAGE permissions for the schema. USAGE is a permission that allows users to actually use the permissions they have been assigned. What's the point of this? I'm not sure. To fix:
|
||||
# You can either grant USAGE to everyone
|
||||
GRANT USAGE ON SCHEMA public TO public;
|
||||
|
||||
# Or grant it just to your read only user
|
||||
GRANT USAGE ON SCHEMA public TO readonlyuser;
|
||||
|
||||
授权首先要能连接(connection)到数据库(pg_hba.conf)上,在模式上要有使用权限(usage),然后是其下的对象的操作权限(如果该对象可以再度分割,如表中有列,对列赋予不同的权限);可以对用户在给定的模式下设定权限(可批可零),或对给定的模式中指定默认的操作权限(批量)。
|
||||
|
||||
撤销权限
|
||||
REVOKE CREATE ON SCHEMA public FROM public;
|
||||
|
||||
第一个 "public" 是模式,第二个 "public" 意思是"所有用户"。
|
||||
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA PUBLIC to freeoa_role; --赋予freeoa_role所有表的SELECT权限
|
||||
|
||||
特殊符号:ALL代表所访问权限,PUBLIC代表所有用户。
|
||||
|
||||
要把新的模式放到路径中来,我们用:
|
||||
SET search_path TO myschema,"$user",public;
|
||||
|
||||
仅对本次会话有效,下次登录又要设置一下。
|
||||
|
||||
或者修改用户的搜索路径,这样即使下次登录也不用重新设置:
|
||||
ALTER USER mobile SET search_path=dba, "$user",public;
|
||||
|
||||
修改模式默认的权限
|
||||
alter default privileges in schema public grant select on tables to web;
|
||||
|
||||
比较通用的模式下对象授权方式多采用:先移除所有用户的所有权限,再有针对性的授权。
|
||||
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC;
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO user_name;
|
||||
|
||||
或者修改具体用户的默认权限
|
||||
ALTER DEFAULT PRIVILEGES
|
||||
FOR ROLE some_role -- Alternatively "FOR USER"
|
||||
IN SCHEMA public
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO user_name;
|
||||
|
||||
这是一个很开放的权限
|
||||
grant all privileges on database dbname to dbuser;
|
||||
|
||||
grant是赋予用户schema下当前表的权限,alter default privileges是赋予用户schema下表的默认权限,这样以后新建表就不用再赋权限了。当我们创建只读账号的时候,需要执行grant和alter default privileges。其次这样可很好地解决每次新建表就要赋一次权限的问题了。
|
||||
|
||||
alter default privileges in schema dba grant select,insert,update,delete on tables to mobile;
|
||||
|
||||
创建的普通用户默认是没有任何权限的。查看表等对象的权限可通过:\dpp来查看,相当直观。
|
||||
|
||||
序列的权限与解决办法
|
||||
|
||||
在insert的时候,指定列插入,主键id是serial类型会默认走sequence的下一个值,但前面只赋予了表的权限,所以会出现下面的问题:
|
||||
|
||||
postgres=> insert into t4 ( name ) values ( 'aa' );
|
||||
ERROR: permission denied for sequence t4_id_seq
|
||||
|
||||
解决方法就是再赋一次sequence的值就行了
|
||||
alter default privileges in schema public grant usage on sequences to user2;
|
||||
|
||||
删除用户
|
||||
|
||||
删除用户和组
|
||||
|
||||
删除用户和组很简单:
|
||||
DROP ROLE role_name;
|
||||
DROP ROLE IF EXISTS role_name;
|
||||
|
||||
删除组role只会删除组的role本身,组的成员并不会被删除。
|
||||
|
||||
postgres=> \c - postgres
|
||||
You are now connected to database "postgres" as user "postgres".
|
||||
postgres=# drop role user2;
|
||||
ERROR: role "user2" cannot be dropped because some objects depend on it
|
||||
DETAIL: privileges for table t5
|
||||
privileges for sequence t5_id_seq
|
||||
privileges for default privileges on new sequences belonging to role postgres in schema public
|
||||
privileges for table t4
|
||||
privileges for default privileges on new relations belonging to role postgres in schema public
|
||||
|
||||
当我们删除用户的时候,会提示有权限依赖,所以我们要删除这些权限
|
||||
|
||||
postgres=# alter default privileges in schema public revoke usage on sequences from user2;
|
||||
ALTER DEFAULT PRIVILEGES
|
||||
postgres=# alter default privileges in schema public revoke select,insert,delete,update on tables from user2;
|
||||
ALTER DEFAULT PRIVILEGES
|
||||
postgres=# revoke select,insert,delete,update on all tables in schema public from user2;
|
||||
REVOKE
|
||||
postgres=# revoke usage on all sequences in schema public from user2;
|
||||
REVOKE
|
||||
postgres=# drop role user2;
|
||||
DROP ROLE
|
||||
|
||||
Pg权限分为两部分,一部分是“系统权限”或者数据库用户的属性,可以授予role或user(两者区别在于login权限);一部分为数据库对象上的操作权限。对超级用户不做权限检查,其它走acl。对于数据库对象,开始只有所有者和超级用户可以做任何操作,其它走acl。在pg里,对acl模型做了简化,组和角色都是role。数据库对象上的权限有:SELECT,INSERT,UPDATE,DELETE,RULE,REFERENCES,TRIGGER,CREATE,TEMPORARY,EXECUTE 和 USAGE等。
|
||||
|
||||
可以用特殊的名字 PUBLIC 把对象的权限赋予系统中的所有角色。 在权限声明的位置上写 ALL,表示把适用于该对象的所有权限都赋予目标角色。
|
||||
|
||||
视图 pg_roles提供访问数据库角色有关信息的接口。 它只是一个 pg_authid 表的公开可读部分的视图,把口令字段用空白填充了。
|
||||
|
||||
pg_roles字段
|
||||
名字
|
||||
|
||||
类型
|
||||
|
||||
引用
|
||||
|
||||
描述
|
||||
|
||||
rolname
|
||||
|
||||
name
|
||||
|
||||
|
||||
|
||||
角色名
|
||||
|
||||
rolsuper
|
||||
|
||||
bool
|
||||
|
||||
|
||||
|
||||
有超级用户权限的角色
|
||||
|
||||
rolcreaterole
|
||||
|
||||
bool
|
||||
|
||||
|
||||
|
||||
可以创建更多角色的角色
|
||||
|
||||
rolcreatedb
|
||||
|
||||
bool
|
||||
|
||||
|
||||
|
||||
可以创建数据库的角色
|
||||
|
||||
rolcatupdate
|
||||
|
||||
bool
|
||||
|
||||
|
||||
|
||||
可以直接更新系统表的角色。(除非这个字段为真,否则超级用户也不能干这个事情。)
|
||||
|
||||
rolcanlogin
|
||||
|
||||
bool
|
||||
|
||||
|
||||
|
||||
可以登录的角色,也就是说,这个角色可以给予初始化会话认证的标识符。
|
||||
|
||||
rolpassword
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
不是口令(总是 ********)
|
||||
|
||||
rolvaliduntil
|
||||
|
||||
timestamptz
|
||||
|
||||
|
||||
|
||||
口令失效日期(只用于口令认证);如果没有失效期,为 NULL
|
||||
|
||||
rolconfig
|
||||
|
||||
text[]
|
||||
|
||||
|
||||
|
||||
运行时配置变量的会话缺省
|
||||
|
||||
|
||||
|
||||
角色属性(Role Attributes)
|
||||
|
||||
一个数据库角色可以有一系列属性,这些属性定义了他的权限。
|
||||
|
||||
属性 说明
|
||||
login 只有具有 LOGIN 属性的角色可以用做数据库连接的初始角色名。
|
||||
superuser 数据库超级用户
|
||||
createdb 创建数据库权限
|
||||
createrole 允许其创建或删除其他普通的用户角色(超级用户除外)
|
||||
replication 做流复制的时候用到的一个用户属性,一般单独设定。
|
||||
password 在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关
|
||||
inherit 用户组对组员的一个继承标志,成员可以继承用户组的权限特性
|
||||
|
||||
在psql中的查看权限的快捷指令
|
||||
|
||||
\dn[S+] [PATTERN] 列出所有模式
|
||||
|
||||
\dp [模式] 列出表,视图和序列的访问权限,同\z
|
||||
|
||||
\du[S+] [PATTERN] 列出角色
|
||||
|
||||
\ddp [模式] 列出默认权限
|
||||
|
||||
\drds [模式1 [模式2]] 列出每个数据库的角色设置
|
||||
|
||||
database、schema、table_seq_view_etc、table_column 分4个级别来授权。
|
||||
|
||||
查看pg_hba.conf 文件,在角色属性中关于password的说明,在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关。
|
||||
|
||||
给已存在用户赋权限
|
||||
|
||||
使用ALTER ROLE 命令。
|
||||
ALTER ROLE name RENAME TO new_name
|
||||
|
||||
ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
|
||||
ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
|
||||
ALTER ROLE name [ IN DATABASE database_name ] RESET configuration_parameter
|
||||
ALTER ROLE name [ IN DATABASE database_name ] RESET ALL
|
||||
|
||||
为角色成员赋权
|
||||
|
||||
查看角色信息
|
||||
|
||||
psql 终端可以用\du 或\du+ 查看,也可以查看系统表
|
||||
select * from pg_roles;
|
||||
select * from pg_user;
|
||||
|
||||
在系统的角色管理中,通常会把多个角色赋予一个组,这样在设置权限时只需给该组设置即可,撤销权限时也是从该组撤销。在PostgreSQL中,首先需要创建一个代表组的角色,之后再将该角色的membership 权限赋给独立的角色即可。
|
||||
|
||||
创建组角色
|
||||
# CREATE ROLE father login nosuperuser nocreatedb nocreaterole noinherit encrypted password 'freeoa';
|
||||
|
||||
给father 角色赋予数据库test 连接权限和相关表的查询权限。
|
||||
# GRANT CONNECT ON DATABASE test to father;
|
||||
test=> GRANT USAGE ON SCHEMA public to father;
|
||||
WARNING: no privileges were granted for "public"
|
||||
|
||||
test=> GRANT SELECT on public.emp to father;
|
||||
|
||||
创建成员角色
|
||||
test=> \c postgres postgres
|
||||
You are now connected to database "postgres" as user "postgres".
|
||||
# CREATE ROLE son1 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'freeoa.net';
|
||||
|
||||
这里创建了son1 角色,并开启inherit 属性。PostgreSQL 里的角色赋权是通过角色继承(INHERIT)的方式实现的。
|
||||
|
||||
将father 角色赋给son1
|
||||
# GRANT father to son1;
|
||||
|
||||
还有另一种方法,就是在创建用户的时候赋予角色权限。
|
||||
# CREATE ROLE son2 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'freeoa.net' in role father;
|
||||
|
||||
用户在public模式下创建的表对于其它用户能看到,但查不了,会报"对关系 prv 权限不够",除非你是这个库的属主。
|
||||
|
||||
可以通过函数来验证模式下的表的相应权限:
|
||||
select has_table_privilege('public.table1','select');
|
||||
select has_table_privilege('dba.webcon_cid_seq','update');
|
||||
|
||||
对sequence类型的授权
|
||||
select 什么都做不了,usage有currval,nextval这两个函数可用,setval不可用,要使用setval就必须有update权限。
|
||||
|
||||
grant usage on sequence web_cid_seq to some_user;
|
||||
|
||||
切换ROLE
|
||||
|
||||
SET ROLE role_name; --切换到role_name用户
|
||||
RESET ROLE; --切换回最初的role
|
||||
|
||||
INHERIT权限:该属性使组成员拥有组的所有权限
|
||||
|
||||
ALTER ROLE freeoa_user INHERIT;
|
||||
|
||||
通过以下方式禁止用户登录
|
||||
|
||||
ALTER ROLE username WITH NOLOGIN;
|
||||
|
||||
第三方的小工具
|
||||
|
||||
somebody created a convenient script for that; pg_grant_read_to_db.sh. This script grants read-only privileges to a specified role on all tables, views and sequences in a database schema and sets them as default.
|
||||
url:https://gist.github.com/jirutka/afa3ce62b1430abf7572
|
||||
|
||||
|
||||
|
||||
参考来源
|
||||
GRANT[http://postgres.cn/docs/9.5/sql-grant.html]
|
||||
ALTER DEFAULT PRIVILEGES[http://postgres.cn/docs/9.5/sql-alterdefaultprivileges.html]
|
310
数据库/postgresql/用户模式权限基础.txt
Normal file
310
数据库/postgresql/用户模式权限基础.txt
Normal file
|
@ -0,0 +1,310 @@
|
|||
一.USER用户管理
|
||||
1.查看用户
|
||||
pg中的role,user,group基本是一样的,只是默认创建的role,group没有登录数据库的权限.用户分为普通用户和超级用户
|
||||
1.使用\du查看数据库中的用户,其中role name是用户名,第二列是用户的属性,第三列表示用户具有哪些成员,例如将suq赋予给brent
|
||||
|
||||
postgres=# \du
|
||||
List of roles
|
||||
Role name | Attributes | Member of
|
||||
-----------+------------------------------------------------------------+-----------
|
||||
brent | | {suq}
|
||||
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
|
||||
suq | 1 connection | {}
|
||||
zdry | Superuser +| {}
|
||||
| Password valid until infinity |
|
||||
2.创建用户
|
||||
1.查看创建用户的语法
|
||||
|
||||
test=# \h create user
|
||||
Command: CREATE USER
|
||||
Description: define a new database role
|
||||
Syntax:
|
||||
CREATE USER name [ [ WITH ] option [ ... ] ]
|
||||
where option can be:
|
||||
SUPERUSER | NOSUPERUSER
|
||||
| CREATEDB | NOCREATEDB
|
||||
| CREATEROLE | NOCREATEROLE
|
||||
| INHERIT | NOINHERIT --继承
|
||||
| LOGIN | NOLOGIN
|
||||
| REPLICATION | NOREPLICATION
|
||||
| BYPASSRLS | NOBYPASSRLS
|
||||
| CONNECTION LIMIT connlimit
|
||||
| [ ENCRYPTED ] PASSWORD 'password'
|
||||
| VALID UNTIL 'timestamp'
|
||||
| IN ROLE role_name [, ...]
|
||||
| IN GROUP role_name [, ...]
|
||||
| ROLE role_name [, ...]
|
||||
| ADMIN role_name [, ...]
|
||||
| USER role_name [, ...]
|
||||
| SYSID uid
|
||||
2.创建一个普通用户
|
||||
|
||||
postgres=# create user test ENCRYPTED password 'test';
|
||||
CREATE ROLE
|
||||
3.为创建一个超级用户
|
||||
|
||||
test=# create user dsg superuser;
|
||||
CREATE ROLE
|
||||
4.创建一个普通用户,并且赋予相关权限
|
||||
|
||||
test=# create user dsg createdb createrole inherit password 'dsg';
|
||||
CREATE ROLE
|
||||
3.修改用户
|
||||
1.查看修改用户语句
|
||||
|
||||
test=# \h alter user
|
||||
Command: ALTER USER
|
||||
Description: change a database role
|
||||
Syntax:
|
||||
ALTER USER role_specification [ WITH ] option [ ... ]
|
||||
where option can be:
|
||||
SUPERUSER | NOSUPERUSER
|
||||
| CREATEDB | NOCREATEDB
|
||||
| CREATEROLE | NOCREATEROLE
|
||||
| INHERIT | NOINHERIT
|
||||
| LOGIN | NOLOGIN
|
||||
| REPLICATION | NOREPLICATION
|
||||
| BYPASSRLS | NOBYPASSRLS
|
||||
| CONNECTION LIMIT connlimit
|
||||
| [ ENCRYPTED ] PASSWORD 'password'
|
||||
| VALID UNTIL 'timestamp'
|
||||
ALTER USER name RENAME TO new_name
|
||||
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
|
||||
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
|
||||
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter
|
||||
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL
|
||||
where role_specification can be:
|
||||
role_name
|
||||
| CURRENT_USER
|
||||
| SESSION_USER
|
||||
2.修改用户为超级用户
|
||||
|
||||
postgres=# alter user test superuser;
|
||||
ALTER ROLE
|
||||
3.将超级用户修改为普通用户
|
||||
|
||||
postgres=# alter user test nosuperuser;
|
||||
ALTER ROLE
|
||||
4.修改用户密码
|
||||
|
||||
test=# alter user dsg password 'test';
|
||||
ALTER ROLE
|
||||
5.修改用户名
|
||||
|
||||
test=# alter user dsg rename to dds;
|
||||
NOTICE: MD5 password cleared because of role rename
|
||||
ALTER ROLE
|
||||
6.锁定/解锁用户,不允许/允许其登录
|
||||
|
||||
test=# alter user test nologin;
|
||||
ALTER ROLE
|
||||
test=# alter user test login;
|
||||
ALTER ROLE
|
||||
7.设置用户的连接数,其中0表示不允许登录,-1表示无限制
|
||||
|
||||
test=# alter user test connection limit 10;
|
||||
ALTER ROLE
|
||||
4.删除用户
|
||||
1.直接删除用户
|
||||
|
||||
test=# drop user dds;
|
||||
DROP ROLE
|
||||
如果用户在数据库中有相关对象,不能直接删除,需要将相关对象所属修改到其它用户中
|
||||
|
||||
test=# drop user dsg;
|
||||
ERROR: role "dsg" cannot be dropped because some objects depend on it
|
||||
DETAIL: owner of table zzz.kkk
|
||||
privileges for schema zzz
|
||||
将dsg的所属用户修改为test:
|
||||
|
||||
test=# reassign owned by dsg to test;
|
||||
REASSIGN OWNED
|
||||
还需要把权限进行收回,再进行删除:
|
||||
|
||||
test=# revoke all on schema zzz from dsg;
|
||||
REVOKE
|
||||
test=# drop user dsg;
|
||||
DROP ROLE
|
||||
|
||||
二.schema模式管理
|
||||
首先介绍一下postgresql中的schema,postgresql中的schema和其它关系型数据库中的schema含义是一致的,在oracle中叫schema或者用户,只是oracle中schema和用户是始终一一对应.
|
||||
在mysql中database和schema是一一对应的.postgresql中user和schema是可以不一致的,相对比其它数据库复杂一点.
|
||||
在创建schema的时候,可以指定schema的所属用户,默认的只有所属用户和超级用户才能在此schema进行对象操作,否则就需要授权.
|
||||
1.使用\dn查看数据库的schema
|
||||
|
||||
test=# \dn
|
||||
List of schemas
|
||||
Name | Owner
|
||||
--------+----------
|
||||
brent | brent
|
||||
public | postgres
|
||||
suq | suq
|
||||
zzz | test
|
||||
(4 rows)
|
||||
|
||||
2.创建schema
|
||||
1.查看创建schema语法
|
||||
|
||||
test=# \h create schema
|
||||
Command: CREATE SCHEMA
|
||||
Description: define a new schema
|
||||
Syntax:
|
||||
CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ]
|
||||
CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ]
|
||||
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ]
|
||||
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification
|
||||
where role_specification can be:
|
||||
user_name
|
||||
| CURRENT_USER
|
||||
| SESSION_USER
|
||||
2.创建一个schema,并且设置所属用户为test:
|
||||
|
||||
test=# create schema zzz authorization test;
|
||||
CREATE SCHEMA
|
||||
|
||||
3.删除schema
|
||||
1.删除schema,如果schema中存在对象,则需要使用cascade选项:
|
||||
|
||||
test=# drop schema zzz;
|
||||
ERROR: cannot drop schema zzz because other objects depend on it
|
||||
DETAIL: table zzz.test depends on schema zzz
|
||||
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
||||
test=# drop schema zzz cascade;
|
||||
NOTICE: drop cascades to table zzz.test
|
||||
DROP SCHEMA
|
||||
|
||||
三.权限管理
|
||||
postgresql中的权限可以大概分为以下几种:
|
||||
SELECT:该权限用来查询表或是表上的某些列,或是视图,序列。
|
||||
INSERT:该权限允许对表或是视图进行插入数据操作,也可以使用COPY FROM进行数据的插入。
|
||||
UPDATE:该权限允许对表或是或是表上特定的列或是视图进行更新操作。
|
||||
DELETE:该权限允许对表或是视图进行删除数据的操作。
|
||||
TRUNCATE:允许对表进行清空操作。
|
||||
REFERENCES:允许给参照列和被参照列上创建外键约束。
|
||||
TRIGGER:允许在表上创建触发器。
|
||||
CREATE:对于数据库,允许在数据库上创建Schema;对于Schema,允许对Schema上创建数据库对象;对于表空间,允许把表或是索引指定到对应的表空间上。
|
||||
CONNECT:允许用户连接到指定的数据库上。
|
||||
TEMPORARY或是TEMP:允许在指定数据库的时候创建临时表。
|
||||
EXECUTE:允许执行某个函数。
|
||||
USAGE:对于程序语言来说,允许使用指定的程序语言创建函数;对于Schema来说,允许查找该Schema下的对象;对于序列来说,允许使用currval和nextval函数;对于外部封装器来说,允许使用外部封装器来创建外部服务器;对于外部服务器来说,允许创建外部表。
|
||||
ALL PRIVILEGES:表示一次性给予可以授予的权限。
|
||||
|
||||
1.schema权限管理
|
||||
首先,如果某个用户需要访问某张表,那么用户首先需要有访问该表所在schema的权限.默认只有schema的所属可以直接操作该schema,其它用户需要授权(public schma除外)
|
||||
1.将schema的权限赋予给指定用户
|
||||
例如,将创建对象权限赋予给brent用户:
|
||||
|
||||
test=# grant create on schema zzz to brent;
|
||||
GRANT
|
||||
例如,将schema中usage权限赋予给brent用户:
|
||||
|
||||
test=> grant usage on schema zzz to brent;
|
||||
GRANT
|
||||
例如,将schema中all权限赋予给brent用户,all表示一次性给予可以授予的所有权限
|
||||
|
||||
test=> grant all on schema zzz to brent;
|
||||
GRANT
|
||||
|
||||
2.表权限管理
|
||||
默认的,如果没有特别的授权,普通用户只能访问表所属为自己的表.超级用户可以访问任何表.如果要访问非自己的表,那么就需要对表进行授权.
|
||||
当我们以brent用户想访问zzz模式下所属用户为test的abc表的时候就会报错:
|
||||
|
||||
test=> select user;
|
||||
user
|
||||
-------
|
||||
brent
|
||||
test=> select * from zzz.abc;
|
||||
ERROR: permission denied for relation abc
|
||||
1.grant,将表的查询和插入权限赋予给brent:
|
||||
|
||||
test=# grant select,insert on zzz.abc to brent;
|
||||
GRANT
|
||||
那么就可以进行查询了:
|
||||
|
||||
(1 row)
|
||||
test=> \c test brent
|
||||
You are now connected to database "test" as user "brent".
|
||||
test=> select * from zzz.abc;
|
||||
id
|
||||
----
|
||||
(0 rows)
|
||||
2.revoke,将表的查询权限收回:
|
||||
|
||||
test=# set search_path=zzz;
|
||||
SET
|
||||
test=# \dt
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+-------+-------
|
||||
zzz | abc | table | test
|
||||
zzz | kkk | table | test
|
||||
(2 rows)
|
||||
test=# revoke select on zzz.abc from brent;
|
||||
REVOKE
|
||||
|
||||
3.角色管理
|
||||
我们除了可以将表的权限赋予给用户,我们还可以将角色赋予给用户,那么用户就会拥有赋予角色的相关权限:
|
||||
|
||||
test=# grant test to brent;
|
||||
GRANT ROLE
|
||||
test=# revoke test from brent;
|
||||
REVOKE ROLE
|
||||
|
||||
4.查询表权限角色列表
|
||||
使用\dp或者\z命令,可以查看表对象上已经分配的权限列表,如下:
|
||||
|
||||
test=# \dp abc
|
||||
Access privileges
|
||||
Schema | Name | Type | Access privileges | Column privileges | Policies
|
||||
--------+------+-------+-------------------+-------------------+----------
|
||||
zzz | abc | table | test=arwdDxt/test+| |
|
||||
| | | brent=a/test +| |
|
||||
| | | uuu=arwdDxt/test | |
|
||||
(1 row)
|
||||
详细的权限说明如下:
|
||||
r -- SELECT ("读")
|
||||
w -- UPDATE ("写")
|
||||
a -- INSERT ("追加")
|
||||
d -- DELETE
|
||||
D -- TRUNCATE
|
||||
x -- REFERENCES
|
||||
t -- TRIGGER
|
||||
X -- EXECUTE
|
||||
U -- USAGE
|
||||
C -- CREATE
|
||||
c -- CONNECT
|
||||
T -- TEMPORARY
|
||||
arwdDxt -- ALL PRIVILEGES (对于表,对其他对象会变化)
|
||||
* -- 用于前述特权的授权选项
|
||||
/yyyy -- 授予该特权的角色
|
||||
|
||||
使用\du可以查看角色之间的成员关系:
|
||||
|
||||
test=# \du brent
|
||||
List of roles
|
||||
Role name | Attributes | Member of
|
||||
-----------+------------+------------
|
||||
brent | | {uuu,test}
|
||||
其中uuu,test是brent的成员,也就是说uuu,test角色被赋予给了brent用户.\du类似与查看oracle中dba_role_privs
|
||||
当我们决定收回某个表给予某个用户的权限的时候,除了需要收回表的权限,还需要检查用户的角色信息,保证用户的角色也没有相关的权限.
|
||||
|
||||
还可以通过查询information_schema.role_table_grants来了解某个用户具有的权限,类似于oralce中dba_tab[sys]_privs
|
||||
test=# select * from information_schema.role_table_grants where grantee='brent';
|
||||
grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy
|
||||
---------+---------+---------------+--------------+------------+----------------+--------------+----------------
|
||||
brent | brent | test | brent | x | INSERT | YES | NO
|
||||
brent | brent | test | brent | x | SELECT | YES | YES
|
||||
brent | brent | test | brent | x | UPDATE | YES | NO
|
||||
brent | brent | test | brent | x | DELETE | YES | NO
|
||||
brent | brent | test | brent | x | TRUNCATE | YES | NO
|
||||
brent | brent | test | brent | x | REFERENCES | YES | NO
|
||||
brent | brent | test | brent | x | TRIGGER | YES | NO
|
||||
brent | brent | test | brent | tt | INSERT | YES | NO
|
||||
brent | brent | test | brent | tt | SELECT | YES | YES
|
||||
brent | brent | test | brent | tt | UPDATE | YES | NO
|
||||
brent | brent | test | brent | tt | DELETE | YES | NO
|
||||
brent | brent | test | brent | tt | TRUNCATE | YES | NO
|
||||
brent | brent | test | brent | tt | REFERENCES | YES | NO
|
||||
brent | brent | test | brent | tt | TRIGGER | YES | NO
|
||||
test | brent | test | zzz | abc | INSERT | YES | NO
|
||||
(15 rows)
|
115
数据库/postgresql/连接用完问题.txt
Normal file
115
数据库/postgresql/连接用完问题.txt
Normal file
|
@ -0,0 +1,115 @@
|
|||
[postgres@vd ~]$ psql -d mydb -U appuser
|
||||
|
||||
psql: FATAL: remaining connection slots are reserved for non-replication superuser connections
|
||||
|
||||
#使用普通用户登录到数据库的时候数据库报错。并且拒绝链接访问。
|
||||
|
||||
[postgres@vd ~]$ psql -U postgres -d mydb
|
||||
|
||||
psql (9.5.4)
|
||||
|
||||
Type "help" for help.
|
||||
|
||||
mydb=# q
|
||||
|
||||
#而使用超级用户登录到该数据库却并没有提示错误。
|
||||
|
||||
[postgres@vd ~]$ psql -U appuser -d mydb
|
||||
|
||||
psql: FATAL: remaining connection slots are reserved for non-replication superuser connections
|
||||
|
||||
[postgres@vd ~]$ psql -U postgres -d mydb
|
||||
|
||||
psql (9.5.4)
|
||||
|
||||
Type "help" for help.
|
||||
|
||||
mydb=> select datname,datconnlimit from pg_database ;
|
||||
|
||||
datname | datconnlimit
|
||||
|
||||
-----------+--------------
|
||||
|
||||
template1 | -1
|
||||
|
||||
template0 | -1
|
||||
|
||||
postgres | -1
|
||||
|
||||
mydb | -1
|
||||
|
||||
(4 rows)
|
||||
|
||||
#数据库链接数并没有进行限制。也就是说链接上线不是数据库自身设置抛出。
|
||||
|
||||
mydb=# select count(*) from pg_stat_activity ;
|
||||
|
||||
count
|
||||
|
||||
-------
|
||||
|
||||
402
|
||||
|
||||
(1 row)
|
||||
|
||||
mydb=# select current_setting('max_connections');
|
||||
|
||||
current_setting
|
||||
|
||||
-----------------
|
||||
|
||||
410
|
||||
|
||||
(1 row)
|
||||
|
||||
mydb=# select current_setting('superuser_reserved_connections');
|
||||
|
||||
current_setting
|
||||
|
||||
-----------------
|
||||
|
||||
10
|
||||
|
||||
(1 row)
|
||||
|
||||
#用超级用户登录上去检查一下链接数是否正常。
|
||||
|
||||
#max_connections是总链接数,
|
||||
|
||||
#superuser_reserved_connections是为超级用户预留的用户数,
|
||||
|
||||
#也就是说 :普通用户最多可以登录数量=max_connections-superuser_reserved_connections
|
||||
|
||||
mydb=# select pg_terminate_backend(pid) from pg_stat_activity where pid<>pg_backend_pid() and pg_stat_activity.state='idle';
|
||||
|
||||
pg_terminate_backend
|
||||
|
||||
----------------------
|
||||
|
||||
t
|
||||
|
||||
...(省略)...
|
||||
|
||||
t
|
||||
|
||||
(352 row)
|
||||
|
||||
#经过协调,相关人员同意将空闲用户都清除出去。使用pg_terminate_backend函数可以从数据库服务器端直接断开这些空闲链接。
|
||||
|
||||
#当然我自己的链接不能被断开。pg_backend_pid()是自己的pid号。
|
||||
|
||||
mydb=# q
|
||||
|
||||
[postgres@vd ~]$ psql -U appuser -d mydb
|
||||
|
||||
psql (9.5.4)
|
||||
|
||||
Type "help" for help.
|
||||
|
||||
mydb=> q
|
||||
|
||||
#再次使用普通用户链接就没有这个问题了。
|
||||
|
||||
追其发生原因,是业务方面不断增加任务需求,而开发人员为了增加任务同时工作数量,在中间件上不断增加链接数,而数据库端却没有增加,不增加数据库上的总链接数是因为怕数据库端内存不够而不敢无休止的增加,希望中间件能协调好复用链接,但没想到中间件最后解决的方法是直接占满数据库链接,起始中间件的日志中也有不少该报错,只是没有发现。
|
||||
|
||||
这里不得不吐嘈一下,目前postgresql数据库还没有共享链接方式,只能是来一个链接起一个进程(非windows),一般是使用中间件来控制链接过多的问题,但是无论是使用什么中间件也不能无休止的增加数据库链接来解决业务需求过多的问题。
|
Loading…
Add table
Add a link
Reference in a new issue