MySQL Connector / Python未明确关闭连接

时间:2017-01-08 15:54:01

标签: python mysql

我有以下内容:

my_cxn

我能够使用cursor2017-01-08T15:16:09.355190Z 132 [Note] Aborted connection 132 to db: 'mydatabase' user: 'myusername' host: 'localhost' (Got an error reading communication packets) 而没有任何明显的失败。我从未明确终止连接,并在我的mysql错误日志中观察到以下消息,但是......

2017-01-06T15:28:45.203067Z 0 [Warning] Changed limits: max_open_files: 1024
    (requested 5000)
2017-01-06T15:28:45.205191Z 0 [Warning] Changed limits: table_open_cache: 431
    (requested 2000)

我是以错误的方式来做这件事的吗?每次我需要运行查询时,初始化连接器和光标会更有效吗?

我需要在mysql配置上查找什么来避免这些中止连接?

另外,我还经常在我的错误日志中观察这些消息:

SharedPreferences sharedPrefs = Utils.getSharedPrefs(getApplicationContext());
int notificationCount = sharedPrefs.getInt("CURRENT_OUTSTANDING_NOTIFICATION_COUNT", 0);

notificationCount++;

SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putInt("CURRENT_OUTSTANDING_NOTIFICATION_COUNT", notificationCount);
editor.commit();

if(notificationCount>1){
    messageTitle = notificationCount+" New Messages";
    messageText = "Last Message Content:"+ messageText;
}

//send notification with the new title and text
...

与上述有关吗?它是什么意思,我该如何解决?

我尝试了涉及/lib/systemd/system/mysql.service.d/limits.conf和其他配置设置的各种解决方案,但无法使其中任何一个工作。

2 个答案:

答案 0 :(得分:2)

这不是配置问题。完成连接后,您应该通过显式调用close来关闭它。通常最好的做法是长时间保持连接,因为创建连接需要时间。从您的代码段中无法判断哪些内容是关闭它的最佳位置 - 只要您完成“#34;完成"用它;也许在你的__main__方法结束时。同样,完成后应该显式关闭游标。通常在每次查询后都会发生这种情况。

所以,可能是这样的:

class FooData(object):
    def __init__(self):
        ...
        try:
            self.my_cnf = os.environ['HOME'] + '/.my.cnf'
            self.my_cxn = mysql.connector.connect(option_files=self.my_cnf)

     def execute_some_query(self, query_info):
        """Runs a single query. Thus it creates a cursor to run the
           query and closes it when it's done."""

        # Note that cursor is not a member variable as it's only for the
        # life of this one query    
        cursor = self.my_cxn.cursor(dictionary=True)
        cursor.execute(...)

        # All done, close the cursor
        cursor.close()

    def close():
        """Users of this class should **always** call close when they are
           done with this class so it can clean up the DB connection."""
        self.my_cxn.close()

您也可以查看the Python with statement以确保始终清理所有内容的好方法。

答案 1 :(得分:0)

我把上面的课改写成这样......

class FooData(object):
    def __init__(self):
        self.myconfig = {
            'option_files': os.environ['HOME'] + '/.my.cnf',
            'database': 'nsdata'
        }
        self.mysqlcxn = None

    def __enter__(self):
        try:
            self.mysqlcxn = mysql.connector.connect(**self.myconfig)
        except mysql.connector.Error as err:
            if err.errno == 2003:
                self.mysqlcxn = None
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if self.mysqlcxn is not None and self.mysqlcxn.is_connected():
            self.mysqlcxn.close()

    def etl(self)
        ...

然后我可以使用with ... as并确保我正在清理。

with FooData() as obj:
    obj.etl()

因此可以正确消除Aborted connection条消息。

Oliver Dain的回答让我走上了正确的道路,而Explaining Python's '__enter__' and '__exit__'对于理解实施我的班级的正确方法非常有帮助。