From 9377a9a0ef8b33769a3d1ee1846adfc2fa155de9 Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Mon, 6 Apr 2020 13:52:58 -0600 Subject: [PATCH] Documentation improvements. --- doc/src/api_manual/cursor.rst | 19 ++++--- doc/src/api_manual/module.rst | 4 +- doc/src/api_manual/soda.rst | 8 +-- doc/src/api_manual/variable.rst | 2 +- doc/src/index.rst | 1 + doc/src/user_guide/connection_handling.rst | 45 ---------------- doc/src/user_guide/ha.rst | 4 +- doc/src/user_guide/installation.rst | 49 ++++++++++++----- doc/src/user_guide/introduction.rst | 3 +- doc/src/user_guide/sql_execution.rst | 1 + doc/src/user_guide/startup.rst | 63 ++++++++++++++++++++++ 11 files changed, 125 insertions(+), 74 deletions(-) create mode 100644 doc/src/user_guide/startup.rst diff --git a/doc/src/api_manual/cursor.rst b/doc/src/api_manual/cursor.rst index 672e494..a167f4f 100644 --- a/doc/src/api_manual/cursor.rst +++ b/doc/src/api_manual/cursor.rst @@ -25,14 +25,19 @@ Cursor Object .. attribute:: Cursor.arraysize - This read-write attribute specifies the number of rows to fetch at a time - internally and is the default number of rows to fetch with the - :meth:`~Cursor.fetchmany()` call. It defaults to 100 meaning to fetch 100 - rows at a time. Note that this attribute can drastically affect the - performance of a query since it directly affects the number of network - round trips that need to be performed. This is the reason for setting it to - 100 instead of the 1 that the DB API recommends. + This read-write attribute can be used to tune the number of rows internally + fetched and buffered by internal calls to the database. The value can + drastically affect the performance of a query since it directly affects the + number of network round trips between Python and the database. For methods + like :meth:`~Cursor.fetchone()` and :meth:`~Cursor.fetchall()` it does not + change how many rows are returned to the application. For + :meth:`~Cursor.fetchmany()` it is the default number of rows to fetch. + Due to the performance benefits, the default ``Cursor.arraysize`` is 100 + instead of the 1 that the DB API recommends. This value means that 100 rows + are fetched by each internal call to the database. + + See :ref:`Tuning Fetch Performance `. .. attribute:: Cursor.bindarraysize diff --git a/doc/src/api_manual/module.rst b/doc/src/api_manual/module.rst index 8cfb9f7..8c976f6 100644 --- a/doc/src/api_manual/module.rst +++ b/doc/src/api_manual/module.rst @@ -1441,8 +1441,8 @@ Exception handling .. attribute:: _Error.isrecoverable Boolean attribute representing whether the error is recoverable or not. - This is False in all cases unless Oracle Database 12.1 is being used on - both the server and the client. + This is False in all cases unless both Oracle Database 12.1 (or later) and + Oracle Client 12.1 (or later) are being used. .. versionadded:: 5.3 diff --git a/doc/src/api_manual/soda.rst b/doc/src/api_manual/soda.rst index efa3bba..d53d270 100644 --- a/doc/src/api_manual/soda.rst +++ b/doc/src/api_manual/soda.rst @@ -416,9 +416,11 @@ SODA Operation Object .. method:: SodaOperation.fetchArraySize(value) - Specifies the numnber of documents that are fetched at a single time from - the SODA collection. A value of 0 will use the default value (100). This - method is only available in Oracle Client 19.5 and higher. + This is a tuning method to specify the number of documents that are + internally fetched in batches by calls to :meth:`~SodaOperation.getCursor()` + and :meth:`~SodaOperation.getDocuments()`. It does not affect how many + documents are returned to the application. A value of 0 will use the default + value (100). This method is only available in Oracle Client 19.5 and higher. As a convenience, the SodaOperation object is returned so that further criteria can be specified by chaining methods together. diff --git a/doc/src/api_manual/variable.rst b/doc/src/api_manual/variable.rst index 457555b..3161f90 100644 --- a/doc/src/api_manual/variable.rst +++ b/doc/src/api_manual/variable.rst @@ -51,7 +51,7 @@ Variable Objects .. attribute:: Variable.outconverter This read-write attribute specifies the method used to convert data from - from the Oracle to Python. The method signature is converter(value) + the Oracle database to Python. The method signature is converter(value) and the expected return value is the value to return to Python. If this attribute is None, the value is returned directly without any conversion. diff --git a/doc/src/index.rst b/doc/src/index.rst index ad5ed68..4da5feb 100644 --- a/doc/src/index.rst +++ b/doc/src/index.rst @@ -35,6 +35,7 @@ User Guide user_guide/cqn.rst user_guide/txn_management.rst user_guide/globalization.rst + user_guide/startup.rst user_guide/ha.rst user_guide/tracing_sql.rst diff --git a/doc/src/user_guide/connection_handling.rst b/doc/src/user_guide/connection_handling.rst index 8e0568c..a45d57c 100644 --- a/doc/src/user_guide/connection_handling.rst +++ b/doc/src/user_guide/connection_handling.rst @@ -1243,51 +1243,6 @@ This is equivalent to executing the following in SQL*Plus: GRANT SYSOPER TO hr; - -Starting and Stopping Oracle Database -===================================== - -cx_Oracle has the capability of starting up the database using a privileged -connection. This example shows a script that could be run as the 'oracle' -operating system user who administers a local database installation on Linux. -It assumes that the environment variable ``ORACLE_SID`` has been set to the SID -of the database that should be started: - -.. code-block:: python - - # the connection must be in PRELIM_AUTH mode to perform startup - connection = cx_Oracle.connect("/", - mode = cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH) - connection.startup() - - # the following statements must be issued in normal SYSDBA mode - connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA, encoding="UTF-8") - cursor = connection.cursor() - cursor.execute("alter database mount") - cursor.execute("alter database open") - -Similarly, cx_Oracle has the ability to shutdown the database using a -privileged connection. This example also assumes that the environment variable -``ORACLE_SID`` has been set: - -.. code-block:: python - - # need to connect as SYSDBA or SYSOPER - connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA) - - # first shutdown() call must specify the mode, if DBSHUTDOWN_ABORT is used, - # there is no need for any of the other steps - connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE) - - # now close and dismount the database - cursor = connection.cursor() - cursor.execute("alter database close normal") - cursor.execute("alter database dismount") - - # perform the final shutdown call - connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL) - - .. _netencrypt: Securely Encrypting Network Traffic to Oracle Database diff --git a/doc/src/user_guide/ha.rst b/doc/src/user_guide/ha.rst index 0eccdda..14d2472 100644 --- a/doc/src/user_guide/ha.rst +++ b/doc/src/user_guide/ha.rst @@ -35,8 +35,8 @@ Network Configuration The operating system TCP and :ref:`Oracle Net configuration ` should be configured for performance and availability. -Options such as `SQLNET.CONNECT_TIMEOUT -`__, +Options such as `SQLNET.OUTBOUND_CONNECT_TIMEOUT +`__, `SQLNET.RECV_TIMEOUT `__ and `SQLNET.SEND_TIMEOUT diff --git a/doc/src/user_guide/installation.rst b/doc/src/user_guide/installation.rst index a81e75c..df73e2f 100644 --- a/doc/src/user_guide/installation.rst +++ b/doc/src/user_guide/installation.rst @@ -440,15 +440,28 @@ To use cx_Oracle with Oracle Instant Client zip files: Restart any open command prompt windows. - To avoid interfering with existing tools that require other Oracle - Client versions, instead of updating the system-wide ``PATH`` variable, you - may prefer to write a batch file that sets ``PATH``, for example:: + To avoid interfering with existing tools that require other Oracle Client + versions, instead of updating the system-wide ``PATH`` variable you can set + the value for each script. + + One way is to set it inside the application before cx_Oracle is used for the + first time: + + .. code-block:: python + + import os + os.environ['PATH'] = r'C:\instantclient_19_3' + os.pathsep + os.environ['PATH] + + Note this only works on Windows. + + Another alternative way to set ``PATH`` is to use a batch file that sets it + before Python is executed, for example:: REM mypy.bat SET PATH=C:\oracle\instantclient_19_3;%PATH% python %* - Invoke this batch file every time you want to run python. + Invoke this batch file every time you want to run Python. Alternatively use ``SET`` to change your ``PATH`` in each command prompt window before you run python. @@ -527,6 +540,9 @@ If you are behind a proxy, specify your proxy server:: python -m pip install cx_Oracle --proxy=http://proxy.example.com:80 --upgrade +The ``--user`` option may also be useful, if you don't have permission to write +to ``/usr``. + The source will be downloaded, compiled, and the resulting binary installed. @@ -537,7 +553,7 @@ Install Oracle Instant Client cx_Oracle requires Oracle Client libraries, which are found in Oracle Instant Client for macOS. These provide the necessary network connectivity allowing cx_Oracle to access an Oracle Database -instance. Oracle Client versions 18, 12 and 11.2 are supported. +instance. Oracle Client versions 19, 18, 12 and 11.2 are supported. To use cx_Oracle with Oracle Instant Client zip files: @@ -547,33 +563,40 @@ To use cx_Oracle with Oracle Instant Client zip files: Python architecture. 2. Unzip the package into a single directory that is accessible to your - application. For example:: + application. For example, in Terminal you could unzip in your home directory:: - mkdir -p /opt/oracle + cd ~ unzip instantclient-basic-macos.x64-19.3.0.0.0dbru.zip -3. Add links to ``$HOME/lib`` or ``/usr/local/lib`` to enable - applications to find the library. For example:: + This will create a directory ``/Users/yourname/instantclient_19_3``. + +3. Add a link to ``$HOME/lib`` or ``/usr/local/lib`` to enable applications to + find Instant Client. If the ``lib`` sub-directory does not exist, you can + create it. For example:: mkdir ~/lib - ln -s /opt/oracle/instantclient_19_3/libclntsh.dylib ~/lib/ + ln -s ~/instantclient_19_3/libclntsh.dylib ~/lib/ + + If you now run ``ls -l ~/lib/libclntsh.dylib`` you will see something like:: + + lrwxr-xr-x 1 yourname staff 48 12 Nov 15:04 /Users/yourname/lib/libclntsh.dylib -> /Users/yourname/instantclient_19_3/libclntsh.dylib Alternatively, copy the required OCI libraries. For example:: mkdir ~/lib - cp /opt/oracle/instantclient_19_3/{libclntsh.dylib.19.1,libclntshcore.dylib.19.1,libnnz19.dylib,libociei.dylib} ~/lib/ + cp ~/instantclient_19_3/{libclntsh.dylib.19.1,libclntshcore.dylib.19.1,libnnz19.dylib,libociei.dylib} ~/lib/ For Instant Client 11.2, the OCI libraries must be copied. For example:: mkdir ~/lib - cp /opt/oracle/instantclient_11_2/{libclntsh.dylib.11.1,libnnz11.dylib,libociei.dylib} ~/lib/ + cp ~/instantclient_11_2/{libclntsh.dylib.11.1,libnnz11.dylib,libociei.dylib} ~/lib/ 4. If you intend to co-locate optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then create a ``network/admin`` subdirectory, if it does not already exist. For example:: - mkdir -p /opt/oracle/instantclient_12_2/network/admin + mkdir -p ~/instantclient_12_2/network/admin This is the default Oracle configuration directory for executables linked with this Instant Client. diff --git a/doc/src/user_guide/introduction.rst b/doc/src/user_guide/introduction.rst index 32a831e..2dce430 100644 --- a/doc/src/user_guide/introduction.rst +++ b/doc/src/user_guide/introduction.rst @@ -13,7 +13,8 @@ Architecture ------------ Python programs call cx_Oracle functions. Internally cx_Oracle dynamically -loads Oracle Client libraries to access Oracle Database. +loads Oracle Client libraries to access Oracle Database. The database can be on +the same machine as Python, or it can be remote. .. _archfig: .. figure:: /images/cx_Oracle_arch.png diff --git a/doc/src/user_guide/sql_execution.rst b/doc/src/user_guide/sql_execution.rst index 19cdcbd..605f00e 100644 --- a/doc/src/user_guide/sql_execution.rst +++ b/doc/src/user_guide/sql_execution.rst @@ -127,6 +127,7 @@ This code ensures that, once the block is completed, the cursor is closed and resources have been reclaimed by the database. In addition, any attempt to use the variable ``cursor`` outside of the block will simply fail. +.. _tuningfetch: Tuning Fetch Performance ------------------------ diff --git a/doc/src/user_guide/startup.rst b/doc/src/user_guide/startup.rst new file mode 100644 index 0000000..a48f2d4 --- /dev/null +++ b/doc/src/user_guide/startup.rst @@ -0,0 +1,63 @@ +.. _startup: + +************************************* +Starting and Stopping Oracle Database +************************************* + +This chapter covers how to start up and shutdown Oracle Database using +cx_Oracle. + +=========================== +Starting Oracle Database Up +=========================== + +cx_Oracle can start up a database instance. A privileged connection is +required. This example shows a script that could be run as the 'oracle' +operating system user who administers a local database installation on Linux. +It assumes that the environment variable ``ORACLE_SID`` has been set to the SID +of the database that should be started: + +.. code-block:: python + + # the connection must be in PRELIM_AUTH mode to perform startup + connection = cx_Oracle.connect("/", + mode = cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH) + connection.startup() + + # the following statements must be issued in normal SYSDBA mode + connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA, encoding="UTF-8") + cursor = connection.cursor() + cursor.execute("alter database mount") + cursor.execute("alter database open") + +To start up a remote database, you may need to configure the Oracle Net +listener to use `static service registration +`_ +by adding a ``SID_LIST_LISTENER`` entry to the database `listener.ora` file. + + +============================= +Shutting Oracle Database Down +============================= + +cx_Oracle has the ability to shutdown the database using a privileged +connection. This example also assumes that the environment variable +``ORACLE_SID`` has been set: + +.. code-block:: python + + # need to connect as SYSDBA or SYSOPER + connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA) + + # first shutdown() call must specify the mode, if DBSHUTDOWN_ABORT is used, + # there is no need for any of the other steps + connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE) + + # now close and dismount the database + cursor = connection.cursor() + cursor.execute("alter database close normal") + cursor.execute("alter database dismount") + + # perform the final shutdown call + connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL)