关于文章 mysql

install linux mysql mysql8

mysql 8.x 安装略有不同 记录一下

linux安装mysql 8.x

mysql 8.x 安装与 5.x 略有不同 这里大概记录一下

my.ini

[mysqld]

port=3306

max_connections=200
max_connect_errors=10
character-set-server=utf8
default-storage-engine=INNODB
default_authentication_plugin=mysql_native_password
[mysql]
default-character-set=utf8
[client]
port=3306
default-character-set=utf8

初始化

./bin/mysqld --initialize

复制出密码来

//修改root的密码

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';  

//创建新用户

CREATE USER 'free'@'%' IDENTIFIED WITH mysql_native_password BY 'free';

// 授权所有权限

GRANT ALL PRIVILEGES ON *.* TO 'free'@'%';

// 授权部分

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON *.* TO 'free'@'%';
asoc linux mariadb mysql
linux mysql tidb

TiDB 用户账户管理

几乎完全兼容mysql的tidb的用户管理


title: TiDB 用户账户管理 category: user guide


TiDB 用户账户管理

用户名和密码

TiDB 将用户账户存储在 mysql.user 系统表里面。每个账户由用户名和 host 作为标识。每个账户可以设置一个密码。

通过 MySQL 客户端连接到 TiDB 服务器,通过指定的账户和密码登陆:

shell> mysql --port 4000 --user xxx --password

使用缩写的命令行参数则是:

shell> mysql -P 4000 -u xxx -p

添加用户

添加用户有两种方式:

  • 通过标准的用户管理的 SQL 语句创建用户以及授予权限,比如 CREATE USERGRANT
  • 直接通过 INSERTUPDATEDELETE 操作授权表。

推荐的方式是使用第一种。第二种方式修改容易导致一些不完整的修改,因此不推荐。还有另一种可选方式是使用第三方工具的图形化界面工具。

下面的例子用 CREATE USERGRANT 语句创建了四个账户:

mysql> CREATE USER 'finley'@'localhost' IDENTIFIED BY 'some_pass';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'localhost' WITH GRANT OPTION;
mysql> CREATE USER 'finley'@'%' IDENTIFIED BY 'some_pass';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'%' WITH GRANT OPTION;
mysql> CREATE USER 'admin'@'localhost' IDENTIFIED BY 'admin_pass';
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> CREATE USER 'dummy'@'localhost';

使用 SHOW GRANTS 可以看到为一个用户授予的权限:

mysql> SHOW GRANTS FOR 'admin'@'localhost';
+-----------------------------------------------------+
| Grants for admin@localhost                          |
+-----------------------------------------------------+
| GRANT RELOAD, PROCESS ON *.* TO 'admin'@'localhost' |
+-----------------------------------------------------+

删除用户

使用 DROP USER 语句可以删除用户,例如:

mysql> DROP USER 'jeffrey'@'localhost';

保留用户账户

TiDB 在数据库初始化时会生成一个 'root'@'%' 的默认账户。

设置资源限制

暂不支持。

设置密码

TiDB 将密码存在 mysql.user 系统数据库里面。只有拥有 CREATE USER 权限,或者拥有 mysql 数据库权限( INSERT 权限用于创建, UPDATE 权限用于更新)的用户才能够设置或修改密码。

CREATE USER 创建用户时可以通过 IDENTIFIED BY 指定密码:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';

为一个已存在的账户修改密码,可以通过 SET PASSWORD FOR 或者 ALTER USER 语句完成:

SET PASSWORD FOR 'root'@'%' = 'xxx';

或者

ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';

更多在官方文档 https://github.com/pingcap/docs-cn

arangodb linux mysql nosql 分布式

arangodb-php 使用

ArangoDB 是一个开源的分布式原生多模型数据库

ArangoDB 是一个开源的分布式原生多模型数据库 (Apache 2 license)。 其理念是: 利用一个引擎,一个 query 语法,一项数据库技术,以及多个数据 模型,来最大力度满足项目的灵活性,简化技术堆栈,简化数据库运维,降低运营成本。

  1. 多数据模型:可以灵活的使用 document, graph, key-value 或者他们的组合作为你的数据模型
  2. 方便的查询:支持类似 SQL 的查询语法 AQL,或者通过 REST 以及其他查询
  3. Ruby 和 JS 扩展:没有语言范围限制,你可以从前台到后台都使用同一种语言
  4. 高性能以及低空间占用:ArangoDB 比其他 NoSQL 都要快,同时占用的空间更小
  5. 简单易用:可以在几秒内启动并且使用,同时可以通过图形界面来管理你的 ArangoDB
  6. 开源且免费:ArangoDB 遵守 Apache 协议

arangodb-php 暂时还没有什么中文资料

arandodb-php的示例代码也不是很清楚 这里尝试了一下curd的简单操作

/**
 * Created by PhpStorm.
 * User: free
 * Date: 17-7-28
 * Time: 下午10:05
 */
//使用方法
//$connection=new arango();
//
//$id=new ArangoDocumentHandler($connection->c);
//
//
//$data=$id->get('user',aaaa);//返回的是json  可先转为数组操作


//composer require triagens/arangodb


//require 'vendor/autoload.php';

use triagens\ArangoDb\Collection as ArangoCollection;
use triagens\ArangoDb\CollectionHandler as ArangoCollectionHandler;
use triagens\ArangoDb\Connection as ArangoConnection;
use triagens\ArangoDb\ConnectionOptions as ArangoConnectionOptions;
use triagens\ArangoDb\DocumentHandler as ArangoDocumentHandler;
use triagens\ArangoDb\Document as ArangoDocument;
use triagens\ArangoDb\Exception as ArangoException;
use triagens\ArangoDb\Export as ArangoExport;
use triagens\ArangoDb\ConnectException as ArangoConnectException;
use triagens\ArangoDb\ClientException as ArangoClientException;
use triagens\ArangoDb\ServerException as ArangoServerException;
use triagens\ArangoDb\Statement as ArangoStatement;
use triagens\ArangoDb\UpdatePolicy as ArangoUpdatePolicy;

class arango
{
    public function __construct(){
        $connectionOptions = [
            // database name
            ArangoConnectionOptions::OPTION_DATABASE => 'free',
            // server endpoint to connect to
            ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://127.0.0.1:8529',
            // authorization type to use (currently supported: 'Basic')
            ArangoConnectionOptions::OPTION_AUTH_TYPE => 'Basic',
            // user for basic authorization
            ArangoConnectionOptions::OPTION_AUTH_USER => 'root',
            // password for basic authorization
            ArangoConnectionOptions::OPTION_AUTH_PASSWD => 'free',
            // connection persistence on server. can use either 'Close' (one-time connections) or 'Keep-Alive' (re-used connections)
            ArangoConnectionOptions::OPTION_CONNECTION => 'Keep-Alive',
            // connect timeout in seconds
            ArangoConnectionOptions::OPTION_TIMEOUT => 3,
            // whether or not to reconnect when a keep-alive connection has timed out on server
            ArangoConnectionOptions::OPTION_RECONNECT => true,
            // optionally create new collections when inserting documents
            ArangoConnectionOptions::OPTION_CREATE => true,
            // optionally create new collections when inserting documents
            ArangoConnectionOptions::OPTION_UPDATE_POLICY => ArangoUpdatePolicy::LAST,
        ];


// turn on exception logging (logs to whatever PHP is configured)
        ArangoException::enableLogging();


        $this->c = new ArangoConnection($connectionOptions);
//        $connect->auth()

    }
}
aql mysql 高级操作

arangodb-aql详细操作

arangodb-aql详细操作


下面介绍以下高级操作:

  • FOR:遍历数组的所有元素。

  • RETURN:生成查询的结果。

  • FILTER:将结果限制为与任意逻辑条件匹配的元素。

  • SORT:强制排序已生成的中间结果的数组。

  • LIMIT:将结果中的元素数减少到至多指定的数字, 可以选择跳过元素 (分页)。

  • LET:将任意值赋给变量。

  • COLLECT:按一个或多个组条件对数组进行分组。也可以计数和聚合。

  • REMOVE:从集合中移除文档。

  • UPDATE:部分更新集合中的文档。

  • REPLACE:完全替换集合中的文档。

  • INSERT:将新文档插入到集合中。

  • UPSERT:更新/替换现有文档, 或在不存在的情况下创建它。

  • WITH:指定查询中使用的集合 (仅在查询开始时)。


FOR

FOR 关键字可以是循环访问数组的所有元素。一般语法是:

FOR variableName IN expression

图遍历还有一个特殊的变体:

FOR vertexVariableName, edgeVariableName, pathVariableName IN traversalExpression

每个由表达式返回的数组元素仅访问一次。在所有情况下, 表达式都需要返回一个数组。也允许空数组。当前数组元素可用于在 variableName 指定的变量中进行进一步处理。

FOR u IN users
RETURN u

返回值

[
{
  "_key": "2427801",
  "_id": "ks/2427801",
  "_rev": "_VeWiZ2i---",
  "id": 1,
  "a": "test",
  "b": [
    "aaaaaaaaaaaaaaaaa"
  ]
}
]

这将遍历阵列用户的所有元素 (注意: 此数组由本例中名为 "users" 的集合中的所有文档组成), 并使当前数组元素在变量 u 中可用. 在本例中没有修改, 只是使用 RETURN 关键字推入结果。

注意: 当迭代基于数组时, 如下所示, 文档的顺序是未定义的, 除非使用排序语句定义了显式排序顺序。

FOR 引入的变量是可用的, 直到 FOR 所放置的范围关闭。

另一个使用静态声明的值数组循环访问的示例:

FOR year IN [ 2011, 2012, 2013 ]
RETURN { "year" : year, "isLeapYear" : year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) }

也允许多个语句的嵌套。当对语句进行嵌套时, 将创建由单个语句返回的数组元素的交叉乘积。

FOR u IN users
FOR l IN locations
  RETURN { "user" : u, "location" : l }

在此示例中, 有两个数组迭代: 在数组用户上的外部迭代加上在数组位置上的内部迭代。内部数组的遍历次数与外部数组中的元素数相同。对于每个迭代, 用户和位置的当前值都可用于在变量中进行进一步的处理。


RETURN

返回语句可用于生成查询结果。必须在数据选择查询的每个块的末尾指定 RETURN 语句, 否则查询结果将是未定义的。在数据修改查询中使用主级别的返回是可选的。

RETURN expression

返回语句所返回的表达式是在返回声明所放置的块中的每个迭代中生成的。这意味着返回语句的结果始终是一个数组。这包括一个空数组, 如果没有与查询匹配的文档, 则返回一个返回值作为数组的一个元素。

要在不修改的情况下返回当前迭代数组中的所有元素, 可以使用以下简单形式:

FOR variableName IN expression
RETURN variableName

当返回允许指定表达式时, 可以执行任意计算来计算结果元素。可将返回的范围中有效的任何变量用于计算。

若要循环访问名为 users 的集合的所有文档并返回完整文档, 可以编写:

FOR u IN users
RETURN u

在 for 循环的每个迭代中, 用户集合的文档被分配给一个变量, 并在本例中未修改返回。若要只返回每个文档的一个属性, 可以使用不同的返回表达式:

FOR u IN users
RETURN u.name

或者要返回多个属性, 可以像这样构造一个对象:

FOR u IN users
RETURN { name: u.name, age: u.age }

注意: 返回将关闭当前范围并消除其中的所有局部变量。在使用子查询时要记住这一点很重要。

FOR u IN users
RETURN { [ u._id ]: u.age }

在本示例中, 每个用户的文档 _id 用作表达式来计算属性键:

[
{
  "users/9883": 32
},
{
  "users/9915": 27
},
{
  "users/10074": 69
}
]

结果包含每个用户一个具有单个键/值对的对象。这通常是不需要的。对于将用户 id 映射到年龄的单个对象, 需要合并单个结果并返回另一个返回:

RETURN MERGE(
  FOR u IN users
    RETURN { [ u._id ]: u.age }
)

.

[
{
  "users/10074": 69,
  "users/9883": 32,
  "users/9915": 27
}
]

请记住, 如果键表达式多次计算为相同的值, 则只有其中一个具有重复名称的键/值对才能生存合并 ()。为了避免出现这种情况, 您可以不使用动态属性名, 而改用静态名称, 并将所有文档属性作为属性值返回:

FOR u IN users
RETURN { name: u.name, age: u.age }

.

[
{
  "name": "John Smith",
  "age": 32
},
{
  "name": "James Hendrix",
  "age": 69
},
{
  "name": "Katie Foster",
  "age": 27
}
]

FILTER

筛选语句可用于将结果限制为与任意逻辑条件匹配的元素。

常规语法

FILTER condition

条件必须是计算结果为 false 或 true 的条件。如果条件结果为 false, 则跳过当前元素, 因此不会进一步处理它, 也不会成为结果的一部分。如果条件为 true, 则不跳过当前元素, 并且可以进一步处理。有关可以在条件中使用的比较运算符、逻辑运算符等的列表, 请参见运算符。

FOR u IN users
FILTER u.active == true && u.age < 39
RETURN u

允许在查询中指定多个筛选语句, 即使在同一块中也是如此。如果使用了多个筛选器语句, 则它们的结果将与逻辑 and 合并, 这意味着所有筛选条件都必须为真, 才能包含元素。

FOR u IN users
FILTER u.active == true
FILTER u.age < 39
RETURN u

在上面的示例中, 用户的所有数组元素的值都为 true, 且属性的值小于 39 (包括 null), 将包括在结果中。将跳过所有其他用户元素, 而不会将其包含在返回结果中。您可以参考从集合访问数据的章节来描述不存在或 null 属性的影响。

操作顺序

请注意, 筛选语句的位置可能会影响查询的结果。测试数据中有16活动用户, 例如:

FOR u IN users
FILTER u.active == true
RETURN u

我们最多可以将结果集限制为5用户:

FOR u IN users
FILTER u.active == true
LIMIT 5
RETURN u

这可能会返回的用户文件, 吉姆, 迭戈, 安东尼, 迈克尔和克洛伊的例子。返回的是未定义的, 因为没有用于确保特定顺序的排序语句。如果我们添加第二个筛选语句只返回女性..。

FOR u IN users
FILTER u.active == true
LIMIT 5
FILTER u.gender == "f"
RETURN u

它可能只返回克洛伊文档, 因为该限制在第二个筛选器之前应用。不超过5文件到达第二个过滤器块, 并且不是所有他们完成性别标准, 即使有超过5活跃女性用户在汇集。通过添加排序块可以实现更具确定性的结果:

FOR u IN users
FILTER u.active == true
SORT u.age ASC
LIMIT 5
FILTER u.gender == "f"
RETURN u

这将返回用户玛丽亚和玛丽。如果按年龄降序排序, 则返回索菲亚、艾玛和麦迪逊文件。但在限制之后的筛选不是很常见, 您可能需要这样的查询:

FOR u IN users
FILTER u.active == true AND u.gender == "f"
SORT u.age ASC
LIMIT 5
RETURN u

放置过滤块的意义在于, 这个单一的关键字可以担当两个 SQL 关键字的角色, 并且具有。因此, AQL 的过滤器与任何其他中间结果、文档属性等的收集聚合体相同。


SORT

排序语句将强制在当前块中已生成的中间结果的数组排序。排序允许指定一个或多个排序条件和方向。一般语法是:

SORT expression direction

按姓氏排序的示例查询 (按升序排列), 然后是名字 (按升序排列), 然后按 id (按降序排列):

FOR u IN users
SORT u.lastName, u.firstName, u.id DESC
RETURN u

指定方向是可选的。排序表达式的默认 (隐式) 方向为升序顺序。若要显式指定排序方向, 可以使用关键字 ASC (升序) 和降序。可以使用逗号分隔多个排序条件。在这种情况下, 为每个表达式 sperately 指定方向。例如

SORT doc.lastName, doc.firstName

将首先按姓氏以升序排序文档, 然后按名字以升序排列。

SORT doc.lastName DESC, doc.firstName

将首先按姓氏按降序排列文档, 然后按名字以升序排序。

SORT doc.lastName, doc.firstName DESC

将首先按姓氏以升序排序文档, 然后按名字降序排列。

注意: 当迭代基于数组时, 文档的顺序始终是未定义的, 除非使用排序定义了显式排序顺序。

请注意, 常量排序表达式可用于指示不需要特定的排序顺序。在优化过程中, AQL 优化器将对常量排序表达式进行优化, 但如果优化器不需要考虑任何特定的排序顺序, 则显式指定它们可能会启用进一步优化。这在收集语句之后尤其如此, 它应该产生一个排序结果。在收集语句后指定额外的排序空值允许 AQL 优化器完全删除收集结果的 post-sorting。


LIMIT

限制语句允许使用偏移量和计数对结果数组进行切片。它将结果中的元素数减少到最多指定的数字。采用了两种一般的限制形式:

LIMIT count
LIMIT offset, count

第一个窗体允许只指定计数值, 而第二个窗体允许指定偏移量和计数。第一个窗体是相同的, 使用第二个窗体的偏移值为0。

FOR u IN users
LIMIT 5
RETURN u

上面的查询返回用户集合的前五文档。它也可以写为限制 0, 5 为相同的结果。它实际上返回的文件是相当任意的, 因为没有明确的排序顺序被指定然而。因此, 限制应通常伴随排序操作。

偏移值指定应跳过结果中的多少元素。它必须是0或更大。count 值指定在结果中最多包含多少元素

FOR u IN users
SORT u.firstName, u.lastName, u.id DESC
LIMIT 2, 5
RETURN u

在上面的示例中, 对用户的文档进行排序, 前两个结果被跳过, 并返回下一个五用户文档。

请注意, 变量和表达式不能用于偏移和计数。在查询编译时, 它们的值必须是已知的, 这意味着您只能使用数字文本和绑定参数。

在与查询中的其他操作相关的情况下, 使用限制是有意义的。特别是在筛选器之前限制操作可以显著地更改结果, 因为这些操作是按照它们在查询中的写入顺序执行的。有关详细示例, 请参见筛选器。


LET

"LET" 语句可用于将任意值赋给变量。然后在让语句所放置的范围中引入变量。

LET variableName = expression

变量在 AQL 中是不可变的, 这意味着它们不能重新:

LET a = [1, 2, 3]  // initial assignment

a = PUSH(a, 4)     // syntax error, unexpected identifier
LET a = PUSH(a, 4) // parsing error, variable 'a' is assigned multiple times
LET b = PUSH(a, 4) // allowed, result: [1, 2, 3, 4]

让语句主要用于声明复杂计算, 并避免在查询的多个部分重复计算相同的值。

FOR u IN users
LET numRecommendations = LENGTH(u.recommendations)
RETURN { 
  "user" : u, 
  "numRecommendations" : numRecommendations, 
  "isPowerUser" : numRecommendations >= 10 
}

在上面的示例中, 使用 "LET" 语句计算出建议的数量, 从而避免在 RETURN 语句中计算两次值。

让我们使用的另一个用例是在子查询中声明一个复杂的计算, 使整个查询更具可读性。

FOR u IN users
LET friends = (
FOR f IN friends 
  FILTER u.id == f.userId
  RETURN f
)
LET memberships = (
FOR m IN memberships
  FILTER u.id == m.userId
    RETURN m
)
RETURN { 
  "user" : u, 
  "friends" : friends, 
  "numFriends" : LENGTH(friends), 
  "memberShips" : memberships 
}

COLLECT

"COLLECT" 关键字可用于按一个或多个组条件对数组进行分组。

COLLECT语句将消除当前范围内的所有局部变量。COLLECT后, 只有由COLLECT本身引入的变量是可用的。

COLLECT的一般语法是:

COLLECT variableName = expression options
COLLECT variableName = expression INTO groupsVariable options
COLLECT variableName = expression INTO groupsVariable = projectionExpression options
COLLECT variableName = expression INTO groupsVariable KEEP keepVariable options
COLLECT variableName = expression WITH COUNT INTO countVariable options
COLLECT variableName = expression AGGREGATE variableName = aggregateExpression options
COLLECT AGGREGATE variableName = aggregateExpression options
COLLECT WITH COUNT INTO countVariable options

选项在所有变体中都是可选的。

对语法进行分组

"COLLECT" 的第一个语法形式仅将结果按表达式中指定的组条件分组。为了进一步处理收集到的结果, 引入了一个新的变量 (由 variableName 指定)。此变量包含组值。

下面是一个查询, 它在美国城市中找到了不同的值, 并使它们可在可变城市中使用:

FOR u IN users
  COLLECT city = u.city
  RETURN { 
    "city" : city 
  }

第二个窗体与第一个窗体相同, 但另外引入了一个变量 (由 groupsVariable 指定), 其中包含掉到组中的所有元素。它的工作方式如下: groupsVariable 变量是一个数组, 其中包含的元素与组中的一样多。该数组的每个成员都是一个 JSON 对象, 其中在 AQL 查询中定义的每个变量的值都绑定到相应的属性。请注意, 这将考虑在收集语句之前定义的所有变量, 而不是在顶层 (任何一个 FOR) 的前面, 除非收集语句本身位于顶层, 在这种情况下, 所有变量都被采用。此外, 请注意, 优化程序可能会将语句移出以用于语句以提高性能。

FOR u IN users
COLLECT city = u.city INTO groups
RETURN { 
  "city" : city, 
  "usersInCity" : groups 
}

在上面的示例中, 数组用户将按属性城市分组。结果是一个新的文档数组, 每个元素都有一个不同的 u. 城市值。元素从原始的数组 (这里: 用户) 每个城市被使可利用在可变的小组。这是由于进入条款。

"COLLECT" 还允许指定多个组条件。单个组条件可以用逗号分隔:

FOR u IN users
COLLECT country = u.country, city = u.city INTO groups
RETURN { 
  "country" : country, 
  "city" : city, 
  "usersInCity" : groups 
}

在上面的示例中, 数组用户首先按国家和城市分组, 对于每个不同的国家和城市组合, 用户将被返回。

丢弃过时的变量

第三种形式的COLLECT允许使用任意 projectionExpression 改写 groupsVariable 的内容:

FOR u IN users
COLLECT country = u.country, city = u.city INTO groups = u.name
RETURN { 
  "country" : country, 
  "city" : city, 
  "userNames" : groups 
}

在上面的例子中, 只有 projectionExpression 是 u 名称。因此, 仅将此属性复制到每个文档的 groupsVariable 中。这可能比将范围内的所有变量复制到 groupsVariable 中要有效得多, 因为它会在没有 projectionExpression 的情况下发生。

下面的表达式也可以用于任意计算:

FOR u IN users
COLLECT country = u.country, city = u.city INTO groups = { 
  "name" : u.name, 
  "isActive" : u.status == "active"
}
RETURN { 
  "country" : country, 
  "city" : city, 
  "usersInCity" : groups 
}

COLLECT还提供一个可选的保留子句, 可用于控制将哪些变量复制到创建的变量中。如果未指定保留子句, 则范围中的所有变量都将作为 sub-attributes 复制到 groupsVariable 中。这是安全的, 但如果范围内有许多变量或变量包含大量数据, 则会对性能产生负面影响。

下面的示例将复制到 groupsVariable 中的变量限制为仅名称。您和 someCalculation 在作用域中的变量也不会被复制到 groupsVariable 中, 因为它们没有在 "保留" 子句中列出:

FOR u IN users
LET name = u.name
LET someCalculation = u.value1 + u.value2
COLLECT city = u.city INTO groups KEEP name 
RETURN { 
  "city" : city, 
  "userNames" : groups[*].name 
}

保持是仅有效的与入的组合。在 "保留" 子句中只能使用有效的变量名。保持支持多个变量名的规范。

组长度计算

"COLLECT" 还提供了一个特殊的计数子句, 可用于有效地确定组成员的数量。

最简单的表单只返回使其进入collect的项的数量:

FOR u IN users
COLLECT WITH COUNT INTO length
RETURN length

上述内容等同于, 但效率高于:

RETURN LENGTH(
  FOR u IN users
    RETURN length
)

使用 count 子句还可以有效地计算每个组中的项数:

FOR u IN users
COLLECT age = u.age WITH COUNT INTO length
RETURN { 
  "age" : age, 
  "count" : length 
}

聚合

COLLECT语句可用于执行每个组的数据聚合。为只确定组长度, 与计数入变异的收集可以使用如前面描述。

对于其他聚合, 可以对收集结果运行聚合函数:

FOR u IN users
COLLECT ageGroup = FLOOR(u.age / 5) * 5 INTO g
RETURN { 
  "ageGroup" : ageGroup,
  "minAge" : MIN(g[*].u.age),
  "maxAge" : MAX(g[*].u.age)
}

REMOVE

  • remove * 关键字可用于从集合中移除文档。在一个 单台服务器, 则在事务中执行文档删除。 完全没有时尚。对于切分集合, 整个删除操作 不是事务性的。

每个 * remove * 操作仅限于单个集合, 而 集合名称 不得为动态。 每个 AQL 查询只允许每个集合使用单 * 删除 * 语句, 并且 它不能后跟访问同一集合的读取操作, 遍历操作或可以读取文档的 AQL 函数。

删除操作的语法为:

REMOVE keyExpression IN collection options
  • collection * 必须包含要删除文档的集合的名称 从。* keyExpression * 必须是包含文档标识的表达式。 这可以是一个字符串 (然后必须包含 文档密钥 或 文档, 它必须包含 * _key * 属性。

因此, 下列查询是等效的:

FOR u IN users
  REMOVE { _key: u._key } IN users

FOR u IN users
  REMOVE u._key IN users

FOR u IN users
  REMOVE u IN users

注意 : 删除操作可以删除任意文档, 并且文档 不需要与前面的 * 声明所产生的相同:

FOR i IN 1..1000
  REMOVE { _key: CONCAT('test', i) } IN users

FOR u IN users
  FILTER u.active == false
  REMOVE { _key: u._key } IN backup

设置查询选项

  • option * 可用于禁止在尝试 删除不存在的文档。例如, 以下查询将失败, 如果一个 to-be 删除的文档不存在:
FOR i IN 1..1000
  REMOVE { _key: CONCAT('test', i) } IN users

通过指定 * ignoreErrors * 查询选项, 可以抑制这些错误, 以便 查询完成:

FOR i IN 1..1000
  REMOVE { _key: CONCAT('test', i) } IN users OPTIONS { ignoreErrors: true }

为了确保在查询返回时已将数据写入磁盘, waitForSync * 查询选项:

FOR i IN 1..1000
  REMOVE { _key: CONCAT('test', i) } IN users OPTIONS { waitForSync: true }

返回已删除的文档

已删除的文档也可以由查询返回。在这种情况下, "REMOVE" 语句后面必须有一个 "RETURN" 语句 (中间的 ' LET ' 语句 也允许). "REMOVE" 引入了 pseudo-value "旧" 来引用已删除的 文件:

REMOVE keyExpression IN collection options RETURN OLD

下面是一个示例, 它使用名为 "已删除" 的变量来捕获被删除的 文件.对于每个已删除的文档, 将返回文档密钥。

FOR u IN users
  REMOVE u IN users 
  LET removed = OLD 
  RETURN removed._key

UPDATE

  • update * 关键字可用于部分更新集合中的文档。在一个 单一服务器, 更新执行事务在一个全有的时尚。 对于切分的集合, 整个更新操作不是事务性的。

每个 * UPDATE * 操作仅限于单个集合, 而 集合名称 不得为动态。 每个 AQL 查询只允许每个集合的单 * UPDATE * 语句, 并且 它不能后跟访问同一集合的读取操作, 遍历操作或可以读取文档的 AQL 函数。 系统属性 * _id , * _key * 和 * _rev * 不能更新, _from * 和 *_to * 可以。

更新操作的两个语法是:

UPDATE document IN collection options
UPDATE keyExpression WITH document IN collection options
  • collection * 必须包含文档的集合名称 进行更新。* document * 必须是包含属性和值的文档 要更新。使用第一个语法时, * document * 也必须包含 * _key * 属性来标识要更新的文档。
FOR u IN users
  UPDATE { _key: u._key, name: CONCAT(u.firstName, " ", u.lastName) } IN users

下面的查询无效, 因为它不包含 * _key * 属性和 因此不可能确定要更新的文档:

FOR u IN users
  UPDATE { name: CONCAT(u.firstName, " ", u.lastName) } IN users

使用第二个语法时, * keyExpression * 提供文档标识。 这可以是一个字符串 (随后必须包含文档密钥) 或 文档, 它必须包含 * _key * 属性。

下列查询是等效的:

FOR u IN users
  UPDATE u._key WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users

FOR u IN users
  UPDATE { _key: u._key } WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users

FOR u IN users
  UPDATE u WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users

更新操作可能会更新不需要相同的任意文档 由前 * FOR * 的陈述所产生的部分:

FOR i IN 1..1000
  UPDATE CONCAT('test', i) WITH { foobar: true } IN users

FOR u IN users
  FILTER u.active == false
  UPDATE u WITH { status: 'inactive' } IN backup

使用文档属性的当前值

"WITH" 子句中不支持 $this "OLD" ( 在 "更新" 之后可用)。若要访问当前属性值, 可以 通常通过 "for" 循环的变量来引用文档, 这是用来 循环访问集合:

FOR doc IN users
  UPDATE doc WITH {
    fullName: CONCAT(doc.firstName, " ", doc.lastName)
  } IN users

如果没有循环, 因为单个文档只更新, 那么 可能不是像上面的变量 ("doc"), 这将让你引用 正在更新的文档:

UPDATE "users/john" WITH { ... } IN users

若要在这种情况下访问当前值, 必须检索文档 并首先存储在变量中:

LET doc = DOCUMENT("users/john")
UPDATE doc WITH {
  fullName: CONCAT(doc.firstName, " ", doc.lastName)
} IN users

可以通过这种方式修改现有属性的当前值, 要递增计数器, 例如:

UPDATE doc WITH {
  karma: doc.karma + 1
} IN users

如果属性 "karma" 还不存在, "karma" 被评估为 * 为 null 。 该表达式 "null + 1" 导致新属性 "karma" 被设置为 * 1 。 如果属性确实存在, 则它会增加 * 1 *。

当然, 数组也可以被突变:

UPDATE doc WITH {
  hobbies: PUSH(doc.hobbies, "swimming")
} IN users

如果属性 "hobbies" 还不存在, 它就会被方便地初始化 作为 "[swimming]", 否则延长。

设置查询选项

  • option * 可用于禁止在尝试 更新不存在的文档或违反唯一的键约束:
FOR i IN 1..1000
  UPDATE {
    _key: CONCAT('test', i)
  } WITH {
    foobar: true
  } IN users OPTIONS { ignoreErrors: true }

更新操作将只更新 * document * 中指定的属性, 并 保持其他属性不变。内部属性 (如 * _id , * _key , * _rev , * _from * 和 * _to ) 不能更新, 并在 * document * 中指定时被忽略。 更新文档将使用服务器生成的值修改文档的修订号。

在更新具有 null 值的属性时, ArangoDB 不会删除该属性 从文档中, 但存储一个空值。删除更新中的属性 操作, 请将它们设置为 null 并提供 * keepNull * 选项:

FOR u IN users
  UPDATE u WITH {
    foobar: true,
    notNeeded: null
  } IN users OPTIONS { keepNull: false }

上述查询将从文档中删除 * notNeeded * 属性, 并更新 * foobar * 属性正常。

还有一个选项 * mergeObjects *, 控制是否将对象内容 如果对象属性同时出现在 * UPDATE * 查询和 to-be 更新的文档。

以下查询将更新后的文档的 * name * 属性设置为精确 在查询中指定的值相同。这是由于 mergeObjects * 选项 被设置为 * false *:

FOR u IN users
  UPDATE u WITH {
    name: { first: "foo", middle: "b.", last: "baz" }
  } IN users OPTIONS { mergeObjects: false }

相反, 下面的查询将合并 * name * 属性的内容。 具有查询中指定值的原始文档:

FOR u IN users
  UPDATE u WITH {
    name: { first: "foo", middle: "b.", last: "baz" }
  } IN users OPTIONS { mergeObjects: true }
  • name * 中存在于 to-be 更新的文档中的属性, 但不在 现在将保留查询。两者中存在的属性将被改写 在查询中指定的值。

注: * mergeObjects * 为 * true * 的默认值 , 因此无需指定 明确.

为了确保数据在更新查询返回时是持久的, 有 * waitForSync * 查询选项:

FOR u IN users
  UPDATE u WITH {
    foobar: true
  } IN users OPTIONS { waitForSync: true }

返回修改后的文档

修改后的文档也可以由查询返回。在这种情况下, "UPDATE 语句需要遵循 "RETURN" 语句 (中间的 ' LET ' 语句 也是允许的)。这些语句可以引用 pseudo-values 的 "OLD" 和 "NEW"。 "OLD" pseudo-value 指更新前的文档修订, 以及 "NEW" 是指更新后的文档修订。

"OLD" 和 "NEW" 都将包含所有文档属性, 即使没有指定 在 update 表达式中。

UPDATE document IN collection options RETURN OLD
UPDATE document IN collection options RETURN NEW
UPDATE keyExpression WITH document IN collection options RETURN OLD
UPDATE keyExpression WITH document IN collection options RETURN NEW

下面是一个示例, 它使用名为 "previous" 的变量来捕获原始 修改前的文档。对于每个已修改的文档, 将返回文档密钥。

FOR u IN users
  UPDATE u WITH { value: "test" } 
  LET previous = OLD 
  RETURN previous._key

下面的查询使用 "NEW" pseudo-value 返回更新的文档, 没有某些系统属性:

FOR u IN users
  UPDATE u WITH { value: "test" } 
  LET updated = NEW 
  RETURN UNSET(updated, "_key", "_id", "_rev")

还可以返回 "旧" 和 "新":

FOR u IN users
  UPDATE u WITH { value: "test" } 
  RETURN { before: OLD, after: NEW }

REPLACE

  • REPLACE * 关键字可用于完全替换集合中的文档。在一个 单台服务器, 替换操作执行事务在一个全有-没有 时尚.对于切分集合, 整个替换操作不是事务性的。

每个 * REPLACE * 操作仅限于单个集合, 而 每个 AQL 查询只允许每个集合使用单 * REPLACE * 语句, 并且 它不能后跟访问同一集合的读取操作, 遍历操作或可以读取文档的 AQL 函数。 系统属性 * _id *, * _key * 和 * _rev * 不能被替换, * _from * 和 * _to * 可以。

替换操作的两个语法为:

REPLACE document IN collection options
REPLACE keyExpression WITH document IN collection options
  • collection * 必须包含文档的集合名称 被替换。* document * 为替换文件。使用第一个语法时, * document * 还必须包含 * _key * 属性, 以标识要替换的文档。
FOR u IN users
  REPLACE { _key: u._key, name: CONCAT(u.firstName, u.lastName), status: u.status } IN users

下面的查询无效, 因为它不包含 * _key * 属性和 因此不可能确定要替换的文档:

FOR u IN users
  REPLACE { name: CONCAT(u.firstName, u.lastName, status: u.status) } IN users

使用第二个语法时, * keyExpression * 提供文档标识。 这可以是一个字符串 (随后必须包含文档密钥) 或 文档, 它必须包含 * _key * 属性。

下列查询是等效的:

FOR u IN users
  REPLACE { _key: u._key, name: CONCAT(u.firstName, u.lastName) } IN users

FOR u IN users
  REPLACE u._key WITH { name: CONCAT(u.firstName, u.lastName) } IN users

FOR u IN users
  REPLACE { _key: u._key } WITH { name: CONCAT(u.firstName, u.lastName) } IN users

FOR u IN users
  REPLACE u WITH { name: CONCAT(u.firstName, u.lastName) } IN users

替换将完全替换现有文档, 但不会修改值 内部属性 (如 * _id , * _key , * _from * 和 * _to *)。替换文档 将使用服务器生成的值修改文档的修订号。

替换操作可以更新不需要相同的任意文档 由前 * FOR * 的陈述所产生的部分:

FOR i IN 1..1000
  REPLACE CONCAT('test', i) WITH { foobar: true } IN users

FOR u IN users
  FILTER u.active == false
  REPLACE u WITH { status: 'inactive', name: u.name } IN backup

设置查询选项

  • option * 可用于禁止在尝试 替换不存在的文档或在违反唯一键约束时:
FOR i IN 1..1000
  REPLACE { _key: CONCAT('test', i) } WITH { foobar: true } IN users OPTIONS { ignoreErrors: true }

为了确保在替换查询返回时数据是持久的, 有 * waitForSync * 查询选项:

FOR i IN 1..1000
  REPLACE { _key: CONCAT('test', i) } WITH { foobar: true } IN users OPTIONS { waitForSync: true }

返回修改后的文档

修改后的文档也可以由查询返回。在这种情况下, "REPLACE" 语句后面必须有一个 "RETURN" 语句 (中间的 ' LET' 语句是 允许的, 太)。"OLD" pseudo-value 可用于引用文档修订版之前 替换, "NEW" 是指替换后的文档修订。

"OLD" 和 "NEW" 都将包含所有文档属性, 即使没有指定 在 "替换" 表达式中。

REPLACE document IN collection options RETURN OLD
REPLACE document IN collection options RETURN NEW
REPLACE keyExpression WITH document IN collection options RETURN OLD
REPLACE keyExpression WITH document IN collection options RETURN NEW

下面是一个示例, 它使用名为 "previous" 的变量返回原始 修改前的文档。对于每个被替换的文档, 文档密钥将 返回:

FOR u IN users
  REPLACE u WITH { value: "test" } 
  LET previous = OLD 
  RETURN previous._key

下面的查询使用 "NEW" pseudo-value 返回替换的 文档 (不含某些系统属性):

FOR u IN users
  REPLACE u WITH { value: "test" } 
  LET replaced = NEW 
  RETURN UNSET(replaced, '_key', '_id', '_rev')

INSERT

  • INSERT * 关键字可用于将新文档插入到集合中。在一个 单服务器, 插入操作在事务中执行。 时尚.对于切分集合, 整个插入操作不是事务性的。

每个 * INSERT * 操作仅限于单个集合, 而 每个 AQL 查询只允许每个集合使用单 * INSERT * 语句, 并且 它不能后跟访问同一集合的读取操作, 遍历操作或可以读取文档的 AQL 函数。

插入操作的语法为:

INSERT document IN collection options

: * INTO * 关键字也允许在 * IN *。

  • collection * 必须包含文档的集合名称 入。* document * 是要插入的文档, 它可能包含也可能不包括
  • _key * 属性。如果不提供 * _key * 属性, ArangoDB 将自动 值为 * _key * 值。插入文档也将自动文档 文档的修订号。
FOR i IN 1..100
  INSERT { value: i } IN numbers

当插入到 edge collection, 在文档中指定属性 * _from * 和 * _to * 为必填项:

FOR u IN users
  FOR p IN products
    FILTER u._key == p.recommendedBy
    INSERT { _from: u._id, _to: p._id } IN recommendations

设置查询选项

  • option * 可用于禁止在违反唯一 关键约束:
FOR i IN 1..1000
  INSERT {
    _key: CONCAT('test', i),
    name: "test",
    foobar: true
  } INTO users OPTIONS { ignoreErrors: true }

为了确保在插入查询返回时数据是持久的, 有 * waitForSync * 查询选项:

FOR i IN 1..1000
  INSERT {
    _key: CONCAT('test', i),
    name: "test",
    foobar: true
  } INTO users OPTIONS { waitForSync: true }

返回插入的文档

插入的文档也可以由查询返回。在这种情况下, "INSERT" 语句可以是 "RETURN" 语句 (中间的 "LET" 语句也是允许的)。 要引用插入的文档, "INSERT" 语句引入了一个 pseudo-value 命名为 "NEW"。

"NEW" 中包含的文档将包含所有属性, 即使是自动生成的 数据库 (例如 "_id"、"_key"、"_rev")。

INSERT document IN collection options RETURN NEW

下面是一个示例, 它使用名为 "inserted" 的变量返回插入的 文件.对于每个插入的文档, 将返回文档密钥:

FOR i IN 1..100
  INSERT { value: i } 
  LET inserted = NEW 
  RETURN inserted._key

WITH

AQL 查询可以选择以 WITH 语句和 查询使用的集合。所有在 WITH 中指定的集合将 在查询开始时读锁定, 除了其他集合的查询 使用 AQL 查询分析器检测到的。

WITH managers, usersHaveManagers
FOR v, e, p IN OUTBOUND 'users/1' GRAPH 'userGraph'
  RETURN { v, e, p }

linux mysql nosql rocksdb

myrocks编译

myrocks编译

先准备编译环境(其实gayhub上都有wiki可是就是英文的。。)

deb系的系统

sudo apt-get update
sudo apt-get -y install g++ cmake libbz2-dev libaio-dev bison \
zlib1g-dev libsnappy-dev libboost-all-dev
sudo apt-get -y install libgflags-dev libreadline6-dev libncurses5-dev \
libssl-dev liblz4-dev gdb git

rpm系的系统

sudo yum install cmake gcc-c++ bzip2-devel libaio-devel bison \
zlib-devel snappy-devel boost-devel
sudo yum install gflags-devel readline-devel ncurses-devel \
openssl-devel lz4-devel gdb git

简单粗暴的下载和编译过程

git clone https://github.com/facebook/mysql-5.6.git
cd mysql-5.6
git submodule init
git submodule update
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_SSL=system \
-DWITH_ZLIB=bundled -DMYSQL_MAINTAINER_MODE=0 -DENABLED_LOCAL_INFILE=1 \
-DENABLE_DTRACE=0 -DCMAKE_CXX_FLAGS="-march=native"
make -j8

make package

。=。不出意外的话 轻松写意的就编译完了。。。但是出了一大堆意外。。。随后我会放出已编译好的包

linux mysql pg postgresql 数据库

postgresql安装

postgresql安装

pgsql/bin/initdb -D /usr/local/pgsql/data
local/pgsql/bin/postgres -D /usr/local/pgsql/data >logfile 2>&1 &
local/pgsql/bin/createdb test
local/pgsql/bin/psql test

账户设置

创建用户
CREATE USER davide WITH PASSWORD 'jw8s0F4';
改密码
ALTER ROLE davide WITH PASSWORD 'hu8jmn3';
让一个角色能够创建其他角色和新的数据库:
ALTER ROLE miriam CREATEROLE CREATEDB;
mysql newsql nosql sql tidb

TiDB 权限管理

TiDB 权限管理


title: 权限管理 category: compatibility


权限管理

TiDB的权限管理系统是按照MySQL的权限管理进行实现,大部分的MySQL的语法和权限类型都是支持的。如果发现行为跟MySQL不一致的地方,欢迎报告issue。

注意:当前版本的权限功能并没有默认开启,需要添加启动参数指定: ./tidb-server -privilege=true 如果不指定参数,权限检查不会生效。将来去掉这个参数(预计RC3)并默认启用权限检查。

1. 用户账户操作

更改密码

set password for 'root'@'%' = 'xxx';

添加用户

create user 'test'@'127.0.0.1' identified by 'xxx';

用户名是大小写敏感的。host则支持模糊匹配,比如:

create user 'test'@'192.168.10.%';

允许test用户从192.168.10子网的任何一个主机登陆。

如果没有指定host,则默认是所有IP均可登陆。如果没有指定密码,默认为空:

create user 'test';

等价于

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

删除用户

drop user 'test'@'%';

这个操作会清除用户在mysql.user表里面的记录项,并且清除在授权表里面的相关记录。

忘记root密码

使用一个特殊的启动参数启动TiDB(需要root权限):

sudo ./tidb-server -skip-grant-table=true

这个参数启动,TiDB会跳过权限系统,然后使用root登陆以后修改密码:

mysql -h 127.0.0.1 -P 4000 -u root

2. 权限相关操作

授予权限

授予xxx用户对数据库test的读权限:

grant Select on test.* to 'xxx'@'%';

为test用户授予所有数据库,全部权限:

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

如果grant的目标用户不存在,TiDB会自动创建用户。

mysql> select * from mysql.user where user='xxxx';
Empty set (0.00 sec)

mysql> grant all privileges on test.* to 'xxxx'@'%' identified by 'yyyyy';
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.user where user='xxxx';
+------|------+
| user | host |
+------|------+
| xxxx | %    |
+------|------+
1 row in set (0.00 sec)

例子中xxxx@%就是自动添加进去的用户。

grant对于数据库或者表的授权,不检查数据库或表是否存在。

mysql> select * from test.xxxx;
ERROR 1146 (42S02): Table 'test.xxxx' doesn't exist

mysql> grant all privileges on test.xxxx to xxxx;
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.tables_priv where user='xxxx';
+------|------+
| user | host |
+------|------+
| xxxx | %    |
+------|------+
1 row in set (0.00 sec)

grant可以模糊匹配地授予数据库和表

mysql> grant all privileges on `te%`.* to genius;
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host,db from mysql.db where user='genius';
+--------|------|-----+
| user   | host | db  |
+--------|------|-----+
| genius | %    | te% |
+--------|------|-----+
1 row in set (0.00 sec)

这个例子中通过%模糊匹配,所有te开头的数据库,都被授予了权限。

收回权限

revoke语句与grant对应:

revoke all privileges on `test`.* from 'genius'@'localhost';

注意revoke收回权限时只做精确匹配,若找不到记录则报错。而grant授予权限时可以使用模糊匹配。

mysql> revoke all privileges on `te%`.* from 'genius'@'%';
ERROR 1141 (42000): There is no such grant defined for user 'genius' on host '%'

关于模糊匹配和转义,字符串和identifier

mysql> grant all privileges on `te\%`.* to 'genius'@'localhost'; Query OK, 0 rows affected (0.00 sec)

这个例子是精确匹配名叫te%的数据库,注意到用了\转义字符。

以单引号包含的,是一个字符串。以反引号包含的,是一个identifier。注意下面区别:

``` mysql> grant all privileges on 'test'. to 'genius'@'localhost'; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''test'. to 'genius'@'localhost'' at line 1

mysql> grant all privileges on test.* to 'genius'@'localhost'; Query OK, 0 rows affected (0.00 sec) ```

如果一些特殊的关键字想做为表名,可以用反引号包含起来。比如:

mysql> create table `select` (id int); Query OK, 0 rows affected (0.27 sec)

查看为用户分配的权限

show grant语句可以查看为用户分配了哪些权限。

show grants for 'root'@'%';

更精确的方式,可以通过直接查看授权表的数据实现。比如想知道,test@%该用户是否拥有对db1.t的Insert权限。

先查看该用户是否拥有全局Insert权限:

select Insert from mysql.user where user='test' and host='%';

如果没有,再查看该用户是否拥有db1数据库级别的Insert权限:

select Insert from mysql.db where user='test' and host='%';

如果仍然没有,则继续判断是否拥有db1.t这张表的Insert权限:

select tables_priv from mysql.tables_priv where user='test' and host='%' and db='db1';

3. 权限系统的实现

授权表

有几张系统表是非常特殊的表,权限相关的数据全部存储在这几张表内。

  • mysql.user 用户账户,全局权限
  • mysql.db 数据库级别的权限
  • mysql.tables_priv 表级别的权限
  • mysql.columns_priv 列级别的权限

这几张表包含了数据的生效范围和权限信息。例如,mysql.user表的部分数据:

mysql> select User,Host,Select_priv,Insert_priv from mysql.user limit 1;
+------|------|-------------|-------------+
| User | Host | Select_priv | Insert_priv |
+------|------|-------------|-------------+
| root | %    | Y           | Y           |
+------|------|-------------|-------------+
1 row in set (0.00 sec)

这条记录中,Host和User决定了root用户从任意主机(%)发送过来的连接请求可以被接受,而Select_privInsert_priv表示用户拥有全局的Select和Insert权限。mysql.user这张表里面的生效范围是全局的。

mysql.db表里面包含的Host和User决定了用户可以访问哪些数据库,权限列的生效范围是数据库。

理论上,所有权限管理相关的操作,都可以通过直接对授权表的CRUD操作完成。

实现层面其实也只是包装了一层语法糖。例如删除用户会执行:

delete from mysql.user where user='test';

但是不推荐用户手动修改授权表。

连接验证

当客户端发送连接请求时,TiDB服务器会对登陆操作进行验证。验证过程先检查mysql.user表,当某条记录的User和Host和连接请求匹配上了,再去验证Password。用户身份基于两部分信息,发起连接的客户端的Host,以及用户名User。如果User不为空,则用户名必须精确匹配。

User+Host可能会匹配user表里面多行,为了处理这种情况,user表的行是排序过的,客户端连接时会依次去匹配,并使用首次匹配到的那一行做权限验证。排序是按Host在前,User在后。

请求验证

连接成功之后,请求验证会检测执行操作是否拥有足够的权限。

对于数据库相关请求(INSERT,UPDATE),先检查mysql.user表里面的用户全局权限,如果权限够,则直接可以访问。如果全局权限不足,则再检查mysql.db表。

user表的权限是全局的,并且不管默认数据库是哪一个。比如user里面有DELETE权限,任何一行,任何的表,任何的数据库。

db表里面,User为空是匹配匿名用户,User里面不能有通配符。Host和Db列里面可以有%_,可以模式匹配。

userdb读到内存也是排序的。

tables_privcolumns_priv 中使用%是类似的,但是在Db, Table_name, Column_name 这些列不能包含%。加载进来时排序也是类似的。

生效时机

TiDB启动时,将一些权限检查的表加载到内存,之后使用缓存的数据来验证权限。系统会周期性的将授权表从数据库同步到缓存,生效则是由同步的周期决定,目前这个值设定的是5分钟。

修改了授权表,如果需要立即生效,可以手动调用:

flush privileges;

4. 限制和约束

一些使用频率偏低的权限当前版本的实现中还未做检查,比如FILE/USAGE/SHUTDOWN/EXECUTE/PROCESS/INDEX等等,未来会陆续完善。

现阶段对权限的支持还没有做到column级别。

mysql newsql nosql pg sql tidb

TiDB 命令行参数

TiDB 命令行参数


title: PD Control 使用说明 category: monitoring


PD Control 使用说明

PD Control 是 PD 的命令行工具,用于获取集群状态信息和调整集群。

源码编译

  1. Go Version 1.7 以上
  2. 在 PD 项目根目录使用 make 命令进行编译,生成 bin/pd-ctl

简单例子

单命令模式:

./pd-ctl store -d -u http://127.0.0.1:2379

交互模式:

./pd-ctl -u http://127.0.0.1:2379

使用环境变量:

export PD_ADDR=http://127.0.0.1:2379
./pd-ctl

命令行参数(flags)

--pd,-u

  • 指定 PD 的地址
  • 默认地址: http://127.0.0.1:2379
  • 环境变量: PD_ADDR

--detach,-d

  • 使用单命令行模式(不进入 readline )
  • 默认值: false

命令(command)

store [delete] \<store_id>

用于显示 store 信息或者删除指定 store。

示例:

>> store            // 显示所有 store 信息
{
  "count": 3,
  "stores": [...]
}
>> store 1          // 获取 store id 为 1 的 store
  ......
>> store delete 1   // 下线 store id 为 1 的 store
  ......

region \<region_id>

用于显示 region 信息。

示例:

>> region                               // 显示所有 region 信息
{
  "count": 1,
  "regions": [......]
}

>> region 2                             // 显示 region id 为 2 的信息
{
  "region": {
      "id": 2,
      ......
  }
  "leader": {
      ......
  }
}

region key [--format=raw|pb|proto|protobuf] \<key>

用于查询某个 key 在哪个 region 上,支持 raw 和 protobuf 格式。

Raw 格式(默认)示例:

>> region key abc
{
  "region": {
    "id": 2,
    ......
  }
}

Protobuf 格式示例:

>> region key --format=pb t\200\000\000\000\000\000\000\377\035_r\200\000\000\000\000\377\017U\320\000\000\000\000\000\372
{
  "region": {
    "id": 2,
    ......
  }
}

member [leader | delete]

用于显示 PD 成员信息或删除指定成员。

示例:

>> member                               // 显示所有成员的信息
{
  "members": [......]
}
>> member leader                        // 显示 leader 的信息
{
  "name": "pd",
  "addr": "http://192.168.199.229:2379",
  "id": 9724873857558226554
}
>> member delete pd2                    // 下线 "pd2"
Success!

config [show | set \<option> \<value>]

用于显示或调整配置信息。

示例:

>> config show                             // 显示 config 的信息
{
  "max-snapshot-count": 3,
  "max-store-down-time": "1h",
  "leader-schedule-limit": 8,
  "region-schedule-limit": 4,
  "replica-schedule-limit": 8,
}

通过调整 leader-schedule-limit 可以控制同时进行 leader 调度的任务个数。 这个值主要影响 leader balance 的速度,值越大调度得越快,设置为 0 则关闭调度。 Leader 调度的开销较小,需要的时候可以适当调大。

>> config set leader-schedule-limit 4       // 最多同时进行 4 个 leader 调度

通过调整 region-schedule-limit 可以控制同时进行 region 调度的任务个数。 这个值主要影响 region balance 的速度,值越大调度得越快,设置为 0 则关闭调度。 Region 调度的开销较大,所以这个值不宜调得太大。

>> config set region-schedule-limit 2       // 最多同时进行 2 个 region 调度

通过调整 replica-schedule-limit 可以控制同时进行 replica 调度的任务个数。 这个值主要影响节点挂掉或者下线的时候进行调度的速度,值越大调度得越快,设置为 0 则关闭调度。 Replica 调度的开销较大,所以这个值不宜调得太大。

>> config set replica-schedule-limit 4      // 最多同时进行 4 个 replica 调度

operator [show | add | remove]

用于显示和控制调度操作。

示例:

>> operator show                            // 显示所有的 operators
>> operator show admin                      // 显示所有的 admin operators
>> operator show leader                     // 显示所有的 leader operators
>> operator show region                     // 显示所有的 region operators
>> operator add transfer-leader 1 2         // 把 region 1 的 leader 调度到 store 2
>> operator add transfer-region 1 2 3 4     // 把 region 1 调度到 store 2,3,4
>> operator add transfer-peer 1 2 3         // 把 region 1 在 store 2 上的副本调度到 store 3
>> operator remove 1                        // 把 region 1 的调度操作删掉

scheduler [show | add | remove]

用于显示和控制调度策略。

示例:

>> scheduler show                             // 显示所有的 schedulers
>> scheduler add grant-leader-scheduler 1     // 把 store 1 上的所有 region 的 leader 调度到 store 1
>> scheduler add evict-leader-scheduler 1     // 把 store 1 上的所有 region 的 leader 从 store 1 调度出去
>> scheduler add shuffle-leader-scheduler     // 随机交换不同 store 上的 leader
>> scheduler add shuffle-region-scheduler     // 随机调度不同 store 上的 region
>> scheduler remove grant-leader-scheduler-1  // 把对应的 scheduler 删掉

title: 参数解释 category: deployment


参数解释

TiDB

--store

  • 用来指定 TiDB 底层使用的存储引擎
  • 默认: "goleveldb"
  • 你可以选择 "memory", "goleveldb", "BoltDB" 或者 "TiKV"。(前面三个是本地存储引擎,而 TiKV 是一个分布式存储引擎)
  • 例如,如果我们可以通过 tidb-server --store=memory 来启动一个纯内存引擎的 TiDB

--path

  • 对于本地存储引擎 "goleveldb", "BoltDB" 来说,path 指定的是实际的数据存放路径
  • 对于 "memory" 存储引擎来说,path 不用设置
  • 对于 "TiKV" 存储引擎来说,path 指定的是实际的 PD 地址。假设我们在 192.168.100.113:2379, 192.168.100.114:2379 和 192.168.100.115:2379 上面部署了 PD,那么 path 为 "192.168.100.113:2379, 192.168.100.114:2379, 192.168.100.115:2379"
  • 默认: "/tmp/tidb"

-L

  • Log 级别
  • 默认: "info"
  • 我们能选择 debug, info, warn, error 或者 fatal

--log-file

  • Log 文件
  • 默认: ""
  • 如果没设置这个参数,log 会默认输出到 "stderr",如果设置了,log 就会输出到对应的文件里面,在每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份

--host

  • TiDB 服务监听 host
  • 默认: "0.0.0.0"
  • TiDB 服务会监听这个 host
  • 0.0.0.0 默认会监听所有的网卡 address。如果有多块网卡,可以指定对外提供服务的网卡,譬如192.168.100.113

-P

  • TiDB 服务监听端口
  • 默认: "4000"
  • TiDB 服务将会使用这个端口接受 MySQL 客户端发过来的请求

--status

  • TiDB 服务状态监听端口
  • 默认: "10080"
  • 这个端口是为了展示 TiDB 内部数据用的。包括 prometheus 统计 以及 pprof
  • Prometheus 统计可以通过 "http://host:status_port/metrics" 访问
  • Pprof 数据可以通过 "http://host:status_port/debug/pprof" 访问

--lease

  • Schema 的租约时间,单位:秒
  • 默认: "1"
  • Schema 的 lease 主要用在 online schema changes 上面。这个值会影响到实际的 DDL 语句的执行时间。千万不要随便改动这个值,除非你能知道相关的内部机制

--socket

  • TiDB 服务使用 unix socket file 方式接受外部连接
  • 默认: ""
  • 譬如我们可以使用 "/tmp/tidb.sock" 来打开 unix socket file

--perfschema

  • 使用 true/false 来打开或者关闭性能 schema
  • 默认: false
  • 值可以是 (true) or (false)。性能 Schema 可以帮助我们在运行时检测内部的执行情况。可以通过 performance schema 获取更多信息。但需要注意,开启性能 Schema,会影响 TiDB 的性能

--privilege

  • 使用 true/false 来打开或者关闭权限功能(用于开发调试)
  • 默认: true
  • 值可以是(true) or (false)。当前版本的权限控制还在完善中,将来会去掉此选项

--skip-grant-table

  • 允许任何人不带密码连接,并且所有的操作不检查权限
  • 默认: false
  • 值可以是(true) or (false)。启用此选项需要有本机的root权限,一般用于忘记密码时重置

--report-status

  • 打开 (true) 或者关闭 (false) 服务状态监听端口
  • 默认: true
  • 值可以为 (true) 或者 (false). (true) 表明我们开启状态监听端口。 (false) 表明关闭

--metrics-addr

  • Prometheus Push Gateway 地址
  • 默认: ""
  • 如果为空,TiDB 不会将统计信息推送给 Push Gateway

--metrics-intervel

  • 推送统计信息到 Prometheus Push Gateway 的时间间隔
  • 默认: 15s
  • 设置为 0 表明不推送统计信息给 Push Gateway

Placement Driver (PD)

-L

  • Log 级别
  • 默认: "info"
  • 我们能选择 debug, info, warn, error 或者 fatal

--log-file

  • Log 文件
  • 默认: ""
  • 如果没设置这个参数,log 会默认输出到 "stderr",如果设置了,log 就会输出到对应的文件里面,在每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份

--config

  • 配置文件
  • 默认: ""
  • 如果你指定了配置文件,PD 会首先读取配置文件的配置。然后如果对应的配置在命令行参数里面也存在,PD 就会使用命令行参数的配置来覆盖配置文件里面的

--name

  • 当前 PD 的名字
  • 默认: "pd"
  • 如果你需要启动多个 PD,一定要给 PD 使用不同的名字

--data-dir

  • PD 存储数据路径
  • 默认: "default.${name}"

--client-urls

  • 处理客户端请求监听 URL 列表
  • 默认: "http://127.0.0.1:2379"
  • 如果部署一个集群,--client-urls 必须指定当前主机的 IP 地址,例如 "http://192.168.100.113:2379",如果是运行在 docker 则需要指定为 "http://0.0.0.0:2379"

--advertise-client-urls

  • 对外客户端访问 URL 列表
  • 默认: ${client-urls}
  • 在某些情况下,譬如 docker,或者 NAT 网络环境,客户端并不能通过 PD 自己监听的 client URLs 来访问到 PD,这时候,你就可以设置 advertise urls 来让客户端访问
  • 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 -p 2379:2379,那么可以设置为 --advertise-client-urls="http://192.168.100.113:2379",客户端可以通过 http://192.168.100.113:2379 来找到这个服务

--peer-urls

  • 处理其他 PD 节点请求监听 URL 列表。
  • default: "http://127.0.0.1:2380"
  • 如果部署一个集群,--peer-urls 必须指定当前主机的 IP 地址,例如 "http://192.168.100.113:2380",如果是运行在 docker 则需要指定为 "http://0.0.0.0:2380"

--advertise-peer-urls

  • 对外其他 PD 节点访问 URL 列表。
  • 默认: ${peer-urls}
  • 在某些情况下,譬如 docker,或者 NAT 网络环境,其他节点并不能通过 PD 自己监听的 peer URLs 来访问到 PD,这时候,你就可以设置 advertise urls 来让其他节点访问
  • 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 -p 2380:2380,那么可以设置为 --advertise-peer-urls="http://192.168.100.113:2380",其他 PD 节点可以通过 http://192.168.100.113:2380 来找到这个服务

--initial-cluster

  • 初始化 PD 集群配置。
  • 默认: "{name}=http://{advertise-peer-url}"
  • 例如,如果 name 是 "pd", 并且 advertise-peer-urls 是 "http://192.168.100.113:2380", 那么 initial-cluster 就是 pd=http://192.168.100.113:2380
  • 如果你需要启动三台 PD,那么 initial-cluster 可能就是 pd1=http://192.168.100.113:2380, pd2=http://192.168.100.114:2380, pd3=192.168.100.115:2380

--join

  • 动态加入 PD 集群
  • 默认: ""
  • 如果你想动态将一台 PD 加入集群,你可以使用 --join="${advertise-client-urls}"advertise-client-url 是当前集群里面任意 PD 的 advertise-client-url,你也可以使用多个 PD 的,需要用逗号分隔

TiKV

TiKV 在命令行参数上面支持一些可读性好的单位转换。

  • 文件大小(以 bytes 为单位): KB, MB, GB, TB, PB(也可以全小写)
  • 时间(以毫秒为单位): ms, s, m, h

-A, --addr

  • TiKV 监听地址
  • 默认: "127.0.0.1:20160"
  • 如果部署一个集群,--addr 必须指定当前主机的 IP 地址,例如 "http://192.168.100.113:20160",如果是运行在 docker 则需要指定为 "http://0.0.0.0:20160"

--advertise-addr

  • TiKV 对外访问地址。
  • 默认: ${addr}
  • 在某些情况下,譬如 docker,或者 NAT 网络环境,客户端并不能通过 TiKV 自己监听的地址来访问到 TiKV,这时候,你就可以设置 advertise addr 来让 客户端访问
  • 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 -p 20160:20160,那么可以设置为 --advertise-addr="192.168.100.113:20160",客户端可以通过 192.168.100.113:20160 来找到这个服务

-L, --log

  • Log 级别
  • 默认: "info"
  • 我们能选择 trace, debug, info, warn, error, 或者 off

--log-file

  • Log 文件
  • 默认: ""
  • 如果没设置这个参数,log 会默认输出到 "stderr",如果设置了,log 就会输出到对应的文件里面,在每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份

-C, --config

  • 配置文件
  • 默认: ""
  • 如果你指定了配置文件,TiKV 会首先读取配置文件的配置。然后如果对应的配置在命令行参数里面也存在,TiKV 就会使用命令行参数的配置来覆盖配置文件里面的

--data-dir

  • TiKV 数据存储路径
  • 默认: "/tmp/tikv/store"

--capacity

  • TiKV 存储数据的容量
  • 默认: 0 (无限)
  • PD 需要使用这个值来对整个集群做 balance 操作。(提示:你可以使用 10GB 来替代 10737418240,从而简化参数的传递)

--pd

  • PD 地址列表。
  • 默认: ""
  • TiKV 必须使用这个值连接 PD,才能正常工作。使用逗号来分隔多个 PD 地址,例如: 192.168.100.113:2379, 192.168.100.114:2379, 192.168.100.115:2379
kv mysql newsql nosql sql

TiDB Binary 部署方案详解

TiDB Binary 部署方案详解


title: TiDB Binary 部署方案详解 category: deployment


# TiDB Binary 部署方案

## 概述

一个完整的 TiDB 集群包括 PD,TiKV 以及 TiDB。启动顺序依次是 PD,TiKV 以及 TiDB。

阅读本章前,请先确保阅读 TiDB 整体架构部署建议

快速了解和试用 TiDB,推荐使用单节点方式快速部署

功能性测试 TiDB,推荐使用功能性测试部署

生产环境使用 TiDB,推荐使用多节点集群模式部署

## 下载官方 Binary

### Linux (CentOS 7+, Ubuntu 14.04+)

```bash # 下载压缩包 wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz wget http://download.pingcap.org/tidb-latest-linux-amd64.sha256

# 检查文件完整性,返回 ok 则正确 sha256sum -c tidb-latest-linux-amd64.sha256

# 解开压缩包 tar -xzf tidb-latest-linux-amd64.tar.gz cd tidb-latest-linux-amd64 ``` ### CentOS 6

注意:我们大部分开发和测试都是在 CentOS 7+, Ubuntu 14.04+ 上进行,CentOS 6 上面并没有经过严格测试,所以不推荐在 CentOS 6 上部署 TiDB 集群

```bash # 下载 CentOS6 压缩包 wget http://download.pingcap.org/tidb-latest-linux-amd64-centos6.tar.gz wget http://download.pingcap.org/tidb-latest-linux-amd64-centos6.sha256

# 检查文件完整性,返回 ok 则正确 sha256sum -c tidb-latest-linux-amd64-centos6.sha256

# 解开压缩包 tar -xzf tidb-latest-linux-amd64-centos6.tar.gz cd tidb-latest-linux-amd64-centos6 ```

## 单节点方式快速部署

我们可以在单机上面,运行和测试 TiDB 集群,请按如下步骤依次启动 PD,TiKV,TiDB:

  1. 启动 PD

    bash ./bin/pd-server --data-dir=pd \ --log-file=pd.log

  2. 启动 TiKV

    bash ./bin/tikv-server --pd="127.0.0.1:2379" \ --data-dir=tikv \ --log-file=tikv.log

  3. 启动 TiDB

    bash ./bin/tidb-server --store=tikv \ --path="127.0.0.1:2379" \ --log-file=tidb.log

  4. 使用官方的 mysql 客户端连接 TiDB

    bash mysql -h 127.0.0.1 -P 4000 -u root -D test

## 多节点集群模式部署 在生产环境中,我们推荐多节点部署 TiDB 集群,首先请参考部署建议

这里我们使用六个节点,部署三个 PD,三个 TiKV,以及一个 TiDB,各个节点以及所运行服务信息如下:

Name Host IP Services
node1 192.168.199.113 PD1, TiDB
node2 192.168.199.114 PD2
node3 192.168.199.115 PD3
node4 192.168.199.116 TiKV1
node5 192.168.199.117 TiKV2
node6 192.168.199.118 TiKV3

请按如下步骤 依次启动 PD 集群,TiKV 集群以及 TiDB:

  1. 在 node1,node2,node3 依次启动 PD

    ```bash ./bin/pd-server --name=pd1 \ --data-dir=pd1 \ --client-urls="http://192.168.199.113:2379" \ --peer-urls="http://192.168.199.113:2380" \ --initial-cluster="pd1=http://192.168.199.113:2380" \ --log-file=pd.log

    ./bin/pd-server --name=pd2 \ --data-dir=pd2 \ --client-urls="http://192.168.199.114:2379" \ --peer-urls="http://192.168.199.114:2380" \ --join="http://192.168.199.113:2379" \ --log-file=pd.log

    ./bin/pd-server --name=pd3 \ --data-dir=pd3 \ --client-urls="http://192.168.199.115:2379" \ --peer-urls="http://192.168.199.115:2380" \ --join="http://192.168.199.113:2379" \ --log-file=pd.log ```

  2. 在 node4,node5,node6 启动 TiKV

    ```bash ./bin/tikv-server --pd="192.168.199.113:2379,192.168.199.114:2379,192.168.199.115:2379" \ --addr="192.168.199.116:20160" \ --data-dir=tikv1 \ --log-file=tikv.log

    ./bin/tikv-server --pd="192.168.199.113:2379,192.168.199.114:2379,192.168.199.115:2379" \ --addr="192.168.199.117:20160" \ --data-dir=tikv2 \ --log-file=tikv.log

    ./bin/tikv-server --pd="192.168.199.113:2379,192.168.199.114:2379,192.168.199.115:2379" \ --addr="192.168.199.118:20160" \ --data-dir=tikv3 \ --log-file=tikv.log ```

  3. 在 node1 启动 TiDB

    bash ./bin/tidb-server --store=tikv \ --path="192.168.199.113:2379,192.168.199.114:2379,192.168.199.115:2379" \ --log-file=tidb.log

  4. 使用官方 mysql 客户端连接 TiDB

    bash mysql -h 192.168.199.113 -P 4000 -u root -D test

注意:在生产环境中启动 TiKV 时,建议使用 --config 参数指定配置文件路径,如果不设置这个参数,TiKV 不会读取配置文件。同样,在生产环境中部署 PD 时,也建议使用 --config 参数指定配置文件路径。

注意:如果使用 nohup 在生产环境中启动集群,需要将启动命令放到一个脚本文件里面执行,否则会出现因为 Shell 退出导致 nohup 启动的进程也收到异常信号退出的问题,具体参考进程异常退出

## 功能性测试部署

如果只是对 TiDB 进行测试,并且机器数量有限,我们可以只启动一台 PD 测试 整个集群。

这里我们使用四个节点,部署一个 PD,三个 TiKV,以及一个 TiDB,各个节点以及所运行服务信息如下:

Name Host IP Services
node1 192.168.199.113 PD1, TiDB
node2 192.168.199.114 TiKV1
node3 192.168.199.115 TiKV2
node4 192.168.199.116 TiKV3

请按如下步骤 依次启动 PD 集群,TiKV 集群以及 TiDB:

  1. 在 node1 启动 PD

    bash ./bin/pd-server --name=pd1 \ --data-dir=pd1 \ --client-urls="http://192.168.199.113:2379" \ --peer-urls="http://192.168.199.113:2380" \ --initial-cluster="pd1=http://192.168.199.113:2380" \ --log-file=pd.log

  2. 在 node2,node3,node4 启动 TiKV

    ```bash ./bin/tikv-server --pd="192.168.199.113:2379" \ --addr="192.168.199.114:20160" \ --data-dir=tikv1 \ --log-file=tikv.log

    ./bin/tikv-server --pd="192.168.199.113:2379" \ --addr="192.168.199.115:20160" \ --data-dir=tikv2 \ --log-file=tikv.log

    ./bin/tikv-server --pd="192.168.199.113:2379" \ --addr="192.168.199.116:20160" \ --data-dir=tikv3 \ --log-file=tikv.log ```

  3. 在 node1 启动 TiDB

    bash ./bin/tidb-server --store=tikv \ --path="192.168.199.113:2379" \ --log-file=tidb.log

  4. 使用官方 mysql 客户端连接 TiDB

    bash mysql -h 192.168.199.113 -P 4000 -u root -D test

linux mysql php

mysql解压安装,以及单机同时运行多个版本

mysql解压安装,以及单机同时运行多个版本

bin/mysqld --initialize --user=mysql 
--basedir=/usr/local/mysql --datadir=/data/mysql
如果失败的话
 bin/mysqld --defaults-file=C:\my.ini --initialize  

 此处需要注意记录生成的临时密码如上文YLi>7ecpe;YP

 cp my-default.cnf /etc/my.cnf

bin/mysqld_safe --defaults-file=my.cnf

my.cnf
basedir=/home/free/sqls
datadir=/home/free/sqls/data
port=9999
server_id=29922
socket=/home/free/sqls/my.socke

设置默认utf-8
character_set_server=utf8 
init_connect='SET NAMES utf8'

mysql --socket=xxxx

set password=password('root');
grant all privileges on *.* to root@'%' identified by 'root';

flush privileges;

grant grant option on *.* to 'root'@'%';
mysql nosql sql

mysql.ini

mysql的配置文件

[client]
port=3306

[mysql]
default-character-set=utf8

[mysqld]
port=3306
server_id=1
character-set-server=utf8
default-storage-engine=MYISAM
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
slow_query_log=0
long_query_time=2
local-infile=0
skip-external-locking
#skip-innodb
#log-bin=mysql-bin
#binlog_format=mixed

max_connections=1000
query_cache_size=0
key_buffer_size=64M
sort_buffer_size=256kb
read_buffer_size=512kb
join_buffer_size=2M
read_rnd_buffer_size=2M
max_allowed_packet=16M
table_open_cache=256
tmp_table_size=64M
max_heap_table_size=64M

myisam_max_sort_file_size=64G
myisam_sort_buffer_size=32M
myisam_repair_threads=1

innodb_buffer_pool_size=64M
innodb_log_file_size=16M
innodb_log_buffer_size=2M
innodb_file_per_table=1
innodb_flush_log_at_trx_commit=1
innodb_lock_wait_timeout=50

[mysqldump]
quick
max_allowed_packet=16M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size=20M
sort_buffer_size=20M
read_buffer=2M
write_buffer=2M

[mysqlhotcopy]
interactive-timeout

[mysqld_safe]
open-files-limit=8192
mysql

mysql添加用户

mysql添加用户

# mysql -u root -p
# 允许本地 IP 访问 localhost, 127.0.0.1
# insert into mysql.user(Host,User,Password) 
values('localhost','zhouz',password('1234'));
# 允许外网 IP 访问
# insert into mysql.user(Host,User,Password) 
values('%','zhouz',password('1234'));
# 刷新授权
# flush privileges;
# 创建数据库
# create database zhouzdb DEFAULT CHARSET 
utf8 COLLATE utf8_general_ci;
# 授予用户通过外网IP对于该数据库的全部权限
# grant all privileges on `zhouzdb`.* to 
'zhouz'@'%' identified by '1234';
# 授予用户在本地服务器对该数据库的全部权限
# grant all privileges on `zhouzdb`.* to
 'zhouz'@'localhost' identified by '1234';


# 刷新权限
# flush privileges;
# 退出 root 重新登录
# \q
# 已新帐号 zhouz 登录,由于使用的是 % 任意IP连接,所以需要指定外部访问IP
# mysql -u zhouz -h 192.168.1.168 -p
# 1234

utf8mb4

创建用户
CREATE USER free@'%' IDENTIFIED  BY '密码'
创建数据库
create database free DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
给数据库加权限
GRANT ALL PRIVILEGES ON `free`.* TO free@'%';
给用户加全县
GRANT ALL PRIVILEGES ON *.* TO 'finley'@'%' WITH GRANT OPTION;