flask sqlalchemy报错:ORA-01000: maximum open cursors exceeded

1. 问题:

DatabaseError: (cx_Oracle.DatabaseError) ORA-01000: maximum open cursors exceeded

2. 原因(book/document/source code):

result.py 

    def fetchone(self):
        """Fetch one row, just like DB-API ``cursor.fetchone()``.

        After all rows have been exhausted, the underlying DBAPI
        cursor resource is released, and the object may be safely
        discarded.

        Calls to :meth:`.ResultProxy.fetchone` after all rows have
        been exhausted will return ``None``.
        After the :meth:`.ResultProxy.close` method is
        called, the method will raise :class:`.ResourceClosedError`.

        .. versionchanged:: 1.0.0 - Added "soft close" behavior which
           allows the result to be used in an "exhausted" state prior to
           calling the :meth:`.ResultProxy.close` method.

        """
        try:
            row = self._fetchone_impl()
            if row is not None:
                return self.process_rows([row])[0]
            else:
                self._soft_close()
                return None
        except BaseException as e:
            self.connection._handle_dbapi_exception(
                e, None, None,
                self.cursor, self.context)

 query.py

    def first(self):
        """Return the first result of this ``Query`` or
        None if the result doesn't contain any row.

        first() applies a limit of one within the generated SQL, so that
        only one primary entity row is generated on the server side
        (note this may consist of multiple result rows if join-loaded
        collections are present).

        Calling :meth:`.Query.first` results in an execution of the underlying query.

        .. seealso::

            :meth:`.Query.one`

            :meth:`.Query.one_or_none`

        """
        if self._statement is not None:
            ret = list(self)[0:1]
        else:
            ret = list(self[0:1])
        if len(ret) > 0:
            return ret[0]
        else:
            return None

3. 验证测试fetchone和first方法区别:

def test_cursor():
    """
    first(): Returns the first record if there is one and closes the connection.
    fetchone(): Returns one row, and leaves the cursor open for you to make additional fetch calls.
    scalar(): Returns a single value if a query results in a single record with one column.
    """
    # 测试fetchone(), 当我们获取到execute_1对象时,可以重复使用该对象的fetchone()方法去获取结果(每次获取的结果不同)
    # 此时cursor会一直存在,第一次调用fetchone()方法时cursor在第一行,返回第一个结果,
    # 再次调用方法时cursor会移动到第二行,以此类推,cursor一直向最后一行移动,直到取不到行数时,cursor才会释放
    sql = text("SELECT * FROM STUDENT")  # 该表返回多条学生记录
    execute_1 = engine.execute(sql)
    for item in range(30):
        result_1 = execute_1.fetchone()
        print(result_1)

    # 测试first(),当获取到execute_2对象时,仅可以对该对象执行一次first()方法,重复执行first()方法会抛异常
    # 异常信息:ResourceClosedError: This result object is closed.
    # 说明first()方法在获取一次结果后该连接已经关闭,不再提供持续的连接
    sql = text("SELECT * FROM STUDENT")
    execute_2 = engine.execute(sql)
    for item in range(30):
        result_2 = execute_2.first()
        print(result_2)

 

4. 解决方式:

        避免使用fetchone,将所有sql查询使用的fetchone()方法替换为first()方法 

 

 

 

参考:

1. 同样的问题:https://blog.csdn.net/heminhao/article/details/73433711

2. 截图1来自《Essential SQLAlchemy》第二章,下载地址:http://vdisk.weibo.com/s/ugG0f_qkHRVY4

3. 截图2来自SQLAlchemy 1.3 Documentation,

     参考:https://docs.sqlalchemy.org/en/latest/core/connections.html#basic-usage

4.oracle查询相关配置信息sql,有点乱,记录一下

---查询oracle db版本信息
select * from v$version where rownum=1;

---查询oracle设置的进程参数
select name,value from v$parameter where name='processes';

---查询当前进程数量或详细进程信息
select count(*) from v$process;
select * from v$process;

---查询游标cursors信息
select sum(a.value) total_cur,
       avg(a.value) avg_cur,
       max(a.value) max_cur,
       s.username,
       s.machine
  from v$sesstat a, v$statname b, v$session s
 where a.statistic# = b.statistic#
       and s.sid=a.sid
       and b.name = 'opened cursors current'
       group by s.username, s.machine
       order by 1 desc;

---查看oracle当前的连接数
select * from v$session where username is not null;

---查看不同用户的连接数
select username,count(username) from v$session where username is not null group by username;

---总连接数
select count(*) from v$session;

---并发连接数
select count(*) from v$session where status='ACTIVE';

---游标设置参数
SELECT value FROM v$parameter WHERE name = 'open_cursors';

select q.sql_text from v$open_cursor o,v$sql q where q.hash_value=o.hash_value and o.sid=217;
select count(*) from v$open_cursor where user_name='STAPUSER';
select count(*) from v$open_cursor;

---通过session查询开启的游标
select a.value,
       s.username,
       s.sid,
       s.serial#
  from v$sesstat a, v$statname b, v$session s
 where a.statistic# = b.statistic#
       and s.sid=a.sid
       and b.name = 'opened cursors current';

select a.value, s.username, s.sid, s.serial#
  from v$sesstat a,
       v$statname b,
       v$session s
 where a.statistic# = b.statistic#
   and s.sid = a.sid
   and b.name = 'opened cursors current'
   and s.username is not null
   and a.value>10;

select * from v$sesstat where ROWNUM<10;

---V_$SESSION表列数
select count(column_name) from dba_tab_columns where table_name='V_$SESSION';

select sid, sql_text, USER_NAME
  from v$open_cursor
 where sid in ('388') and user_name='STAPUSER';

select  sid ,
        sql_text, 
        count(*) as "OPEN CURSORS", 
        USER_NAME 
  from  v$open_cursor 
 where  sid in ('388') 
        group by count(*);

SELECT max(a.value) as highest_open_cur, 
       p.value as max_open_cur
  FROM v$sesstat a,
      v$statname b,
      v$parameter p
 WHERE a.statistic# = b.statistic#
   and b.name = 'opened cursors current'
   and p.name = 'open_cursors'
       group by p.value;

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值