体验使用mysqldb操作mysql5.7的json类型

看到推送的消息说,mysql 5.7 ga版本出来了,说是有更好的性能,对于多核CPU、固态硬盘、锁有着更好的优化。在这一版本里面,mysql也终于有了json数据结构,虽说现在还不能跟mongodb这样的文档性数据库做比拟,但这已经是关系型数据库的一大改进了。 

mysql5.7 ga版本说是10 26号才发布下载地址. 那我们就先测试下最新的rc版本。最近的版本是mysql5.7.8,mysql在5.7.8的时候,才加入了json功能。 对于这样的新鲜功能,我总是那么的好奇。 今天就体验下mysql5.7.8 json的功能,还要看python MySQLdb对于这样的json支持程度。 

1. 安装相关工具

yum -y install gcc-c++ ncurses-devel cmake make perl gcc autoconf automake zlib libxml libgcrypt libtool bison

2. 清理环境, 以前要把以前的mysql-sever mysql-* 卸载个干净。 

3. mysql源码包下载

mysql5.7.8源码包下载: 
http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.8-rc.tar.gz

如果mysql的版本有更新,可以自己找找递增的版本
http://mirrors.sohu.com/mysql/

4. 创建mysql用户, 组及目录

# groupadd mysql
# useradd -g mysql -d /home/mysql mysql
# mkdir /data/mysql/

5. 注意事项

从MySQL 5.7.5开始Boost库是必需的,下载Boost库,在解压后复制到/usr/local/boost目录下,然后重新cmake并在后面的选项中加上选项 -DWITH_BOOST=/usr/local/include/boost/

新版本mysql-5.7.8需求boost_1_57_0, 下载地址如下:

wget -c http://git.typecodes.com/libs/ccpp/boost_1_57_0.tar.bz2
tar -jxf boost_1_57_0.tar.bz2 && cd boost_1_57_0/
./bootstrap.sh
./b2 stage threading=multi link=shared
./b2 install threading=multi link=shared
cd ~ && rm -rf boost_1_57_0*

boost安装之后,咱们开始编译mysql,首先需要cmake

cmake \
-DCMAKE_BUILD_TYPE:STRING=Release \
-DCMAKE_INSTALL_PREFIX:PATH=/usr/local/mysql \
-DCOMMUNITY_BUILD:BOOL=ON \
-DENABLED_PROFILING:BOOL=ON \
-DENABLE_DEBUG_SYNC:BOOL=OFF \
-DINSTALL_LAYOUT:STRING=STANDALONE \
-DMYSQL_DATADIR:PATH=/data/mysql \
-DMYSQL_MAINTAINER_MODE:BOOL=OFF \
-DWITH_EMBEDDED_SERVER:BOOL=ON \
-DWITH_EXTRA_CHARSETS:STRING=all \
-DWITH_SSL:STRING=bundled \
-DWITH_UNIT_TESTS:BOOL=OFF \
-DWITH_ZLIB:STRING=bundled \
-DENABLE_DTRACE=OFF \
-DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/include/boost/

CMAKE_INSTALL_PREFIX:指定MySQL程序的安装目录,默认/usr/local/mysql
DEFAULT_CHARSET:指定服务器默认字符集,默认latin1
DEFAULT_COLLATION:指定服务器默认的校对规则,默认latin1_general_ci
ENABLED_LOCAL_INFILE:指定是否允许本地执行LOAD DATA INFILE,默认OFF
WITH_COMMENT:指定编译备注信息
WITH_xxx_STORAGE_ENGINE:指定静态编译到mysql的存储引擎,MyISAM,MERGE,MEMBER以及CSV四种引擎默认即被编译至服务器,不需要特别指定。
WITHOUT_xxx_STORAGE_ENGINE:指定不编译的存储引擎
SYSCONFDIR:初始化参数文件目录
MYSQL_DATADIR:数据文件目录
MYSQL_TCP_PORT:服务端口号,默认3306
MYSQL_UNIX_ADDR:socket文件路径,默认/tmp/mysql.sock

编译安装

# make && make install

以root初始化操作时要加–user=mysql参数,生成一个随机密码(注意保存登录时用),密码是放在/home/mysql/.mysql_secret文件里面的。

# cd /home/mysql
# bin/mysqld –initialize –user=mysql –basedir=/user/local/mysql –datadir=/data/mysql/

8. 创建配置文件

拷贝配置文件模板为新的mysql配置文件,
cd /usr/local/mysql/support-files;cp my-default.cnf /etc/my.cnf


可按需修改新的配置文件选项, 不修改配置选项, mysql则按默认配置参数运行. 
如下是我修改配置文件/etc/my.cnf, 用于设置编码为utf8以防乱码

[mysqld]

character_set_server=utf8
init_connect=’SET NAMES utf8′

[client]
default-character-set=utf8


9. 配置mysql服务开机自动启动

拷贝启动文件到/etc/init.d/下并重命令为mysqld

# cp /user/local/mysql/support-files/mysql.server /etc/init.d/mysqld
增加执行权限

# chmod 755 /etc/init.d/mysqld

这时候mysql一切都完毕了,我们启动mysql。

 /etc/init.d/mysqld start


这里在贴下,编译mysql5.7.8的时候,遇到的一些问题。 

第一个问题

新版的mysql在默认初始化的时候,会在你的家目录下生成一个含有密码的文件。一开始没好好看文档,以前跟5.6一样空密码,结果搞得很头疼。 另外在使用mysql_install_db 进行新实例初始化会提示下面信息:


./bin/mysql_install_db –user=mysql –datadir=/data/mysql/

[ERROR]   Failed to execute –bootstrap –datadir=/data/mysql –lc-messages-dir=/usr/share/mysql –lc-messages=en_US
— server log begin —
mysqld: [Warning] –bootstrap is deprecated. Please consider using –initialize instead
— server log end —
可以看到提示 mysql_install_db 已经不再推荐使用了,建议改成 mysqld –initialize 完成实例初始化,如果想以前那样空密码模式也是可以了,需要–initialize-insecure 参数,指定初始化数据库,并且设为空密码

改成 mysqld –initialize 后,如果 datadir 指向的目标目录下已经有数据文件,则会有类似提示:

./bin/mysqld –user=mysql –basedir=/usr/local/mysql –datadir=/data/mysql –initial –initialize-insecure

[ERROR] –initialize specified but the data directory has files in it. Aborting.
[ERROR] Aborting


因此,需要先确保 datadir 目标目录下是空的,避免误操作破坏已有数据。如果想强制初始化,那么直接删除data目录就可以了。 

另外,在初始化时如果加上 –initial-insecure,则会创建空密码的 root@localhost 账号,否则会创建带密码的 root@localhost 账号,密码直接写在 log-error 日志文件中(在5.6版本中是放在 ~/.mysql_secret 文件里,更加隐蔽,不熟悉的话可能会无所适从)

./bin/mysqld –user=mysql –basedir=/user/local/mysql –datadir=/data/mysql –initialize

[Warning] Insecure configuration for –secure-file-priv: Current value does not restrict location of generated files. Consider setting it to a valid, non-empty path.

初始化完毕后,如果没使用新版本的客户端登入,还会报告类似下面的错误:

mysql -uroot -p
Enter password:
ERROR 1862 (HY000): Your password has expired. To log in you must change it using a client that supports expired passwords.
上面的错误提示意思是需要用当前版本的客户端登入。需要确定你的环境变量是否有冲突,也就是说,别的文件的mysql bin 还存在。 

遇到的第二个问题:

CMake Error at cmake/boost.cmake:76 (MESSAGE):
  You can download it with -DDOWNLOAD_BOOST=1 -DWITH_BOOST=<directory>
 
  This CMake script will look for boost in <directory>.  If it is not there,
  it will download and unpack it (in that directory) for you.
 
  If you are inside a firewall, you may need to use an http proxy:
 
  export http_proxy=http://example.com:80
 
Call Stack (most recent call first):
  cmake/boost.cmake:228 (COULD_NOT_FIND_BOOST)
  CMakeLists.txt:452 (INCLUDE)
— Configuring incomplete, errors occurred!

解决的方法,删除以前的boost,下载boost,并重新编译安装就可以了。 另外cmake的时候,加入boost的相关参数    cmake  -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/boost

既然安装成功,那么我们开始使用python操作mysqldb .

创建表:

CREATE TABLE `blogs` (
  `doc` json DEFAULT NULL,
  `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

import MySQLdb
import json


class MysqlStore(object):
    def __init__(self,mysql_dict):
        self.host = mysql_dict['host']
        self.port = mysql_dict['port']
        self.db = mysql_dict['db']
        self.user = mysql_dict['user']
        self.pw = mysql_dict['pw']
        self._get_connection()
        self._get_cursor()

    def _get_connection(self):
        self.conn = MySQLdb.connect(host=self.host, user=self.user,passwd=self.pw,db=self.db,charset="utf8")
        self.conn.autocommit(True)

    def _get_cursor(self):
        self.cursor = self.conn.cursor()

    def close(self):
        self._conn.close()

config = {
    'host':'127.0.0.1',
    'user':'root',
    'port':3306,
    'pw':'xiaorui.cc',
    'db':'json'
}
new_blog = {
    'page_id': '1',
    'title': 'welcome to xiaorui.cc',
}

mysql = MysqlStore(config)
sql = "INSERT INTO blogs (doc) VALUES (%s)"

mysql.cursor.execute(sql,(json.dumps(new_blog),))

查询数据.

select = (
    "SELECT JSN_EXTRACT(doc, '.page_id'), "
    "JSN_EXTRACT(doc, '.title') "
    "FROM blogs "
    "WHERE JSN_CONTAINS(doc, JSN_OBJECT('page_id', %s))"
)

mysql.cursor.execute(select, ('1',))

for row in mysql.cursor.fetchall():
    print("%s | %s" % (row[0], row[1]))

话说,MySQLdb原本就支持json,换句话说,对于MySQLdb来说,他发送的都是sql语句而已,原本就没有就不用接口的适配。   原本以为json是新结构,MySQLdb不支持,在github中提了一个issue问题。 


总结,  python mysqldb,pymysql都支持mysql的json结构。 





大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

2 Responses

  1. 草泥马 2016年9月4日 / 下午4:06

    用mongodb

  2. 何莉莉 2016年9月4日 / 下午4:06

    lai’zi 来自

发表评论

邮箱地址不会被公开。 必填项已用*标注